public OutdoorNode SidewalkEdgeNodeFromWorldPoint(Vector3 worldPosition) { if (grid == null) { Start(); } float percentX = ((worldPosition.x - plane.transform.position.x) + gridWorldSize.x / 2) / gridWorldSize.x; float percentY = ((worldPosition.z - plane.transform.position.z) + gridWorldSize.y / 2) / gridWorldSize.y; percentX = Mathf.Clamp01(percentX); percentY = Mathf.Clamp01(percentY); int x = Mathf.RoundToInt((gridSizeX - 1) * percentX); int y = Mathf.RoundToInt((gridSizeY - 1) * percentY); if (grid [x, y].sidewalkEmptyEdge) { try { return(grid [x, y]); } catch (NullReferenceException) { Start(); return(grid [x, y]); } } else { // Find the nearest sidewalk edge node List <OutdoorNode> potentialEdgeNodes = new List <OutdoorNode>(); foreach (OutdoorNode node in GetCrossSection(6, grid[x, y])) { if (node.sidewalkEmptyEdge) { potentialEdgeNodes.Add(node); } } if (potentialEdgeNodes.Count == 1) { return(potentialEdgeNodes [0]); } else if (potentialEdgeNodes.Count > 1) { float distance = 100; OutdoorNode toReturn = potentialEdgeNodes [0]; foreach (OutdoorNode node in potentialEdgeNodes) { float newDistance = Vector3.Distance(node.worldPosition, grid [x, y].worldPosition); if (newDistance < distance) { distance = newDistance; toReturn = node; } } return(toReturn); } } return(new OutdoorNode()); }
public void GetOutdoorPath(Vector3 pos) { if (outdoorGrid == null) { outdoorGrid = GameObject.Find("OutdoorPlane").GetComponent <OutdoorGrid>(); } outdoorTargetNode = outdoorGrid.NodeFromWorldPoint(pos); OutdoorPathRequestManager.RequestPath(transform.position, pos, OnOutdoorPathFound); }
int GetDistance(OutdoorNode nodeA, OutdoorNode nodeB) { int dstX = Mathf.Abs(nodeA.gridX - nodeB.gridX); int dstY = Mathf.Abs(nodeA.gridY - nodeB.gridY); if (dstX > dstY) { return(14 * dstY + 10 * (dstX - dstY)); } return(14 * dstX + 10 * (dstY - dstX)); }
Vector3[] RetracePath(OutdoorNode startNode, OutdoorNode endNode) { List <OutdoorNode> path = new List <OutdoorNode>(); OutdoorNode currentNode = endNode; while (currentNode != startNode) { path.Add(currentNode); currentNode = currentNode.parent; } Vector3[] waypoints = SimplifyPath(path); Array.Reverse(waypoints); return(waypoints); }
public OutdoorNode GetClosestWalkableNode(OutdoorNode toCheck, int distance, Vector3 seekerPos, Vector3 targetPos) // Gets the closest walkable node from an unwalkable one. If a target is generated that is unwalkable, this will allow the customer to generate a path to the closest node available to it // distance of 1 creates 3x3 node grid centered around the unwalkable node // 2 creates 5x5, etc { print("GetClosestWalkable"); List <OutdoorNode> neighbours = new List <OutdoorNode>(); OutdoorNode lowest = new OutdoorNode(); for (int x = -distance; x <= distance; x++) { for (int y = -distance; y <= distance; y++) { if (x == 0 && y == 0) { continue; } int checkX = toCheck.gridX + x; int checkY = toCheck.gridY + y; if (checkX >= 0 && checkX < gridSizeX && checkY >= 0 && checkY < gridSizeY) { if (grid[checkX, checkY].walkable) { neighbours.Add(grid[checkX, checkY]); } } } } List <OutdoorNode> walkableCloseNeighbours = new List <OutdoorNode> (); if (neighbours.Count > 0) { // get closest node } else if (neighbours.Count == 0) { if (!(distance++ > 5)) { return(GetClosestWalkableNode(toCheck, distance++, seekerPos, targetPos)); } } return(lowest); }
public List <OutdoorNode> GetCrossSection(int units, OutdoorNode node) { List <OutdoorNode> neighbours = new List <OutdoorNode> (); for (int x = -units; x <= units; x++) { for (int y = -units; y <= units; y++) { if (x == 0 && y == 0) { continue; } int checkX = node.gridX + x; int checkY = node.gridY + y; if (checkX >= 0 && checkX < gridSizeX && checkY >= 0 && checkY < gridSizeY) { neighbours.Add(grid[checkX, checkY]); } } } return(neighbours); }
public void CreateGrid() { OutdoorNode[,] lastGrid = new OutdoorNode[gridSizeX, gridSizeY]; bool lastGridExists = false; try { for (int i = 0; i < gridSizeX; i++) { for (int j = 0; j < gridSizeY; j++) { OutdoorNode refNode = grid[i, j]; lastGrid [i, j] = new OutdoorNode(refNode.empty, refNode.walkable, refNode.drivable, refNode.crosswalk, refNode.buildable, refNode.movementPenalty, refNode.worldPosition, i, j); lastGridExists = true; } } } catch (Exception ex) { // print (ex); // Just wait till next time the method calls } grid = new OutdoorNode[gridSizeX, gridSizeY]; Vector3 worldBottomLeft = transform.position - Vector3.right * gridWorldSize.x / 2 - Vector3.forward * gridWorldSize.y / 2; List <OutdoorNode> buildableNodes = new List <OutdoorNode> (); foreach (GameObject plane in buildablePlanes) { Destroy(plane.gameObject); } buildablePlanes.Clear(); for (int x = 0; x < gridSizeX; x++) { for (int y = 0; y < gridSizeY; y++) { Vector3 worldPoint = worldBottomLeft + Vector3.right * (x * nodeDiameter + nodeRadius) + Vector3.forward * (y * nodeDiameter + nodeRadius); bool walkable = (Physics.CheckSphere(worldPoint, nodeRadius, sidewalkMask)); bool drivable = (Physics.CheckSphere(worldPoint, nodeRadius, roadMask)); bool crosswalk = (Physics.CheckSphere(worldPoint, nodeRadius, crosswalkMask)); bool buildable = (Physics.CheckSphere(worldPoint, nodeRadius, buildableMask)); int movementPenalty = 0; if (drivable && !crosswalk) { movementPenalty = 2000; } else if (drivable && crosswalk) { movementPenalty = 5; } else if (walkable) { movementPenalty = 0; } else if (buildable) { movementPenalty = 25; } bool empty = false; if (!Physics.CheckSphere(worldPoint, nodeRadius)) { empty = true; movementPenalty = 75; } grid [x, y] = new OutdoorNode(empty, walkable, drivable, crosswalk, buildable, movementPenalty, worldPoint, x, y); if (buildable) { OutdoorNode toAdd = grid [x, y]; buildableNodes.Add(toAdd); } } } // --------------------------------------------------- // Build the visible buildable zone // --------------------------------------------------- Vector2 bottomLeft = GetBottomLeft(); foreach (OutdoorNode oNode in buildableNodes) { GameObject newPlane = Instantiate(dm.gridPlanePrefab); newPlane.name = "BuildableZone"; newPlane.tag = "BuildableZone"; newPlane.layer = 15; newPlane.GetComponent <MeshRenderer> ().material = outdoorDefaultTileTexture; newPlane.AddComponent <OutdoorNodePlane> (); newPlane.GetComponent <OutdoorNodePlane> ().gridX = grid [oNode.gridX, oNode.gridY].gridX; newPlane.GetComponent <OutdoorNodePlane> ().gridY = grid [oNode.gridX, oNode.gridY].gridY; newPlane.transform.localScale = new Vector3(nodeDiameter / 10, .1f, nodeDiameter / 10); OutdoorNode refNode = GetNodeFromGridIndex(oNode.gridX, oNode.gridY); grid [refNode.gridX, refNode.gridY].buildable = true; Vector3 planeLocation = grid [oNode.gridX, oNode.gridY].worldPosition; newPlane.transform.position = new Vector3(planeLocation.x, storeBoundariesPlane.transform.position.y, planeLocation.z); newPlane.transform.eulerAngles = new Vector3(0, 0, 0); newPlane.transform.parent = storeBoundariesPlane.transform; buildablePlanes.Add(newPlane); } // --------------------------------------------------- CheckWalkable(); }
public OutdoorNode GetNodeFromReference(OutdoorNode ref_) { return(grid [ref_.gridX, ref_.gridY]); }
int distanceFromBuildableZone = 12; // Max amount of nodes to be expanded per use public int CreateEmptyGridPlanes() { // returns the distance that is being expanded // Creates planes for the empty nodes surrounding the buildable zone (not every single empty node) w/ a distance of distanceFromBuildableZone //int gridXMax = (int) dm.buildableDimensions.x; //int gridZMax = (int) dm.buildableDimensions.y; Vector2 buildableBottomLeft = Vector2.zero; // This will be the gridX and gridY of the node that is the bottom left of the buildable zone float xPos = 100; float zPos = -100; foreach (GameObject FloorTile in buildablePlanes) { // the bottom left node is the lowest x value and highest z value of the edgenodes if (FloorTile.transform.position.x < xPos) { buildableBottomLeft.x = FloorTile.GetComponent <OutdoorNodePlane> ().gridX; xPos = FloorTile.transform.position.x; } if (FloorTile.transform.position.z > zPos) { buildableBottomLeft.y = FloorTile.GetComponent <OutdoorNodePlane> ().gridY; zPos = FloorTile.transform.position.z; } } foreach (OutdoorNode node in grid) { if (node.buildable) { if (node.gridY == grid[(int)buildableBottomLeft.x, (int)buildableBottomLeft.y].gridY) { for (int i = 0; i < distanceFromBuildableZone; i++) { GameObject newPlane = Instantiate(dm.gridPlanePrefab); newPlane.name = "ExpandableNode"; newPlane.tag = "ExpandableZ"; newPlane.GetComponent <MeshRenderer> ().material = greenOutdoorNode_Transparent; OutdoorNode expandableNodeRef = GetNodeFromGridIndex(node.gridX, node.gridY + (i + 1)); // Z direction newPlane.AddComponent <OutdoorNodePlane>().gridX = expandableNodeRef.gridX; newPlane.GetComponent <OutdoorNodePlane> ().gridY = expandableNodeRef.gridY; newPlane.transform.localScale = new Vector3(nodeDiameter / 10, .1f, nodeDiameter / 10); Vector3 planeLocation = expandableNodeRef.worldPosition; newPlane.transform.position = new Vector3(planeLocation.x, storeBoundariesPlane.transform.position.y, planeLocation.z); tempEmptyPlanes.Add(newPlane); } } OutdoorNode refNode = GetNodeFromGridIndex((int)(buildableBottomLeft.x + dm.buildableDimensions.x + 1), (int)buildableBottomLeft.y); if (node.gridX == refNode.gridX) { for (int i = 0; i < distanceFromBuildableZone; i++) { GameObject newPlane = Instantiate(dm.gridPlanePrefab); newPlane.name = "ExpandableNode"; newPlane.tag = "ExpandableX"; newPlane.GetComponent <MeshRenderer> ().material = greenOutdoorNode_Transparent; OutdoorNode expandableNodeRef = GetNodeFromGridIndex(node.gridX + (i + 2), node.gridY); // X direction newPlane.AddComponent <OutdoorNodePlane> ().gridX = expandableNodeRef.gridX; newPlane.GetComponent <OutdoorNodePlane> ().gridY = expandableNodeRef.gridY; newPlane.transform.localScale = new Vector3(nodeDiameter / 10, .1f, nodeDiameter / 10); Vector3 planeLocation = expandableNodeRef.worldPosition; newPlane.transform.position = new Vector3(planeLocation.x, storeBoundariesPlane.transform.position.y, planeLocation.z); tempEmptyPlanes.Add(newPlane); } } } } return(distanceFromBuildableZone); }
IEnumerator FindPath(Vector3 startPos, Vector3 targetPos) { Vector3[] waypoints = new Vector3[0]; bool pathSuccess = false; OutdoorNode startNode = grid.NodeFromWorldPoint(startPos); OutdoorNode targetNode = grid.NodeFromWorldPoint(targetPos); if (true) { Heap <OutdoorNode> openSet = new Heap <OutdoorNode>(grid.MaxSize); HashSet <OutdoorNode> closedSet = new HashSet <OutdoorNode>(); openSet.Add(startNode); while (openSet.Count > 0) { OutdoorNode currentNode = openSet.RemoveFirst(); closedSet.Add(currentNode); if (currentNode == targetNode) { pathSuccess = true; break; } foreach (OutdoorNode neighbour in grid.GetNeighbours(currentNode)) { int extraMovementPenalty = 0; foreach (OutdoorNode neighbour_ in grid.GetNeighbours(neighbour)) { if (neighbour_.drivable || neighbour_.empty) { extraMovementPenalty = 10; } } if (closedSet.Contains(neighbour)) { continue; } int newMovementCostToNeighbour = currentNode.gCost + GetDistance(currentNode, neighbour) + neighbour.movementPenalty + extraMovementPenalty; if (newMovementCostToNeighbour < neighbour.gCost || !openSet.Contains(neighbour)) { neighbour.gCost = newMovementCostToNeighbour; neighbour.hCost = GetDistance(neighbour, targetNode); neighbour.parent = currentNode; if (!openSet.Contains(neighbour)) { openSet.Add(neighbour); } else { openSet.UpdateItem(neighbour); } } } } } yield return(null); if (pathSuccess) { waypoints = RetracePath(startNode, targetNode); } requestManager.FinishedProcessingPath(waypoints, targetPos, pathSuccess); }