private void bakingGridPoint(Vector3 startPoint, Vector3 gameObjectCenter, Vector3 gameObjectSize, Vector3 position) { NavMesh2DNode newNode = new NavMesh2DNode(); newNode.position = position; newNode.neighbours = new List <int> (); // check if there is obstacles exist at/near(within unit error) the node Collider2D center = Physics2D.OverlapPoint(new Vector2(newNode.position.x, newNode.position.y)); Collider2D top = Physics2D.OverlapPoint(new Vector2(newNode.position.x, newNode.position.y + unitError)); Collider2D bottom = Physics2D.OverlapPoint(new Vector2(newNode.position.x, newNode.position.y - unitError)); Collider2D left = Physics2D.OverlapPoint(new Vector2(newNode.position.x - unitError, newNode.position.y)); Collider2D right = Physics2D.OverlapPoint(new Vector2(newNode.position.x + unitError, newNode.position.y)); Collider2D topLeft = Physics2D.OverlapPoint(new Vector2(newNode.position.x - unitError, newNode.position.y + unitError)); Collider2D topRight = Physics2D.OverlapPoint(new Vector2(newNode.position.x + unitError, newNode.position.y + unitError)); Collider2D bottomLeft = Physics2D.OverlapPoint(new Vector2(newNode.position.x - unitError, newNode.position.y - unitError)); Collider2D bottomRight = Physics2D.OverlapPoint(new Vector2(newNode.position.x + unitError, newNode.position.y - unitError)); if ((center != null && center.gameObject.GetComponent <NavMesh2DObstacle>() != null) || (top != null && top.gameObject.GetComponent <NavMesh2DObstacle>() != null) || (bottom != null && bottom.gameObject.GetComponent <NavMesh2DObstacle>() != null) || (left != null && left.gameObject.GetComponent <NavMesh2DObstacle>() != null) || (right != null && right.gameObject.GetComponent <NavMesh2DObstacle>() != null) || (topLeft != null && topLeft.gameObject.GetComponent <NavMesh2DObstacle>() != null) || (topRight != null && topRight.gameObject.GetComponent <NavMesh2DObstacle>() != null) || (bottomLeft != null && bottomLeft.gameObject.GetComponent <NavMesh2DObstacle>() != null) || (bottomRight != null && bottomRight.gameObject.GetComponent <NavMesh2DObstacle>() != null) || newNode.position.x < gameObjectCenter.x - gameObjectSize.x / 2 || newNode.position.x > gameObjectCenter.x + gameObjectSize.x / 2 || newNode.position.y < gameObjectCenter.y - gameObjectSize.y / 2 || newNode.position.y > gameObjectCenter.y + gameObjectSize.y / 2) { // there is obstacle or out of bound newNode.id = obstacleNodes.nodes.Count; obstacleNodes.nodes.Add(newNode); } else if (!navMeshNodes.nodes.Contains(newNode) && !obstacleNodes.nodes.Contains(newNode)) { newNode.id = navMeshNodes.nodes.Count; navMeshNodes.nodes.Add(newNode); // find neighbours for (int k = 0; k < navMeshNodes.nodes.Count - 1; k++) { float distance = Vector3.Distance(navMeshNodes.nodes [k].position, navMeshNodes.nodes [navMeshNodes.nodes.Count - 1].position); if (navMeshNodes.nodes [k].neighbours.Count < 8 && distance <= unitLength) { Vector2 origin = new Vector2(navMeshNodes.nodes [k].position.x, navMeshNodes.nodes [k].position.y); Vector2 dest = new Vector2(navMeshNodes.nodes [navMeshNodes.nodes.Count - 1].position.x, navMeshNodes.nodes [navMeshNodes.nodes.Count - 1].position.y); RaycastHit2D hit = Physics2D.Linecast(origin, dest); if (hit.transform == null || hit.transform.gameObject.GetComponent <NavMesh2DObstacle>() == null) { navMeshNodes.nodes [k].neighbours.Add(navMeshNodes.nodes [navMeshNodes.nodes.Count - 1].id); navMeshNodes.nodes [navMeshNodes.nodes.Count - 1].neighbours.Add(navMeshNodes.nodes [k].id); } } } } }
/// <summary> /// Set the target position of the agent. /// </summary> public void setTarget(Vector3 target) { this.target = target; target.z = 0; // find the path if (TopDown2DNavMeshBaker.navMeshNodes == null) { TopDown2DNavMeshBaker.init(); } NavMesh2DNode closestStart = TopDown2DNavMeshBaker.navMeshNodes.findNearestNode(transform.position); NavMesh2DNode closestGoal = TopDown2DNavMeshBaker.navMeshNodes.findNearestNode(target); List <IAStarable <Vector3> > map = new List <IAStarable <Vector3> > (); for (int i = 0; i < TopDown2DNavMeshBaker.navMeshNodes.nodes.Count; i++) { IAStarable <Vector3> newNode = (IAStarable <Vector3>)TopDown2DNavMeshBaker.navMeshNodes.nodes [i]; newNode.heuristicFunction = () => { return(Vector3.Distance(newNode.value, closestGoal.position)); }; map.Add(newNode); } StartCoroutine(AStarAlgorithm.findPath <Vector3> (map, (IAStarable <Vector3>)closestStart, (IAStarable <Vector3>)closestGoal, pathHandler)); }
/// <summary> /// Handle the recieved path. /// </summary> public void pathHandler(List <IAStarable <Vector3> > result) { if (result != null) { List <NavMesh2DNode> newPath = new List <NavMesh2DNode> (); if (path == null) { path = new List <Vector3> (); } else if (path.Count > 0) { path.Clear(); } for (int i = 0; i < result.Count; i++) { NavMesh2DNode newNode = (NavMesh2DNode)result [i]; newNode.heuristicFunction = null; newPath.Add(newNode); } Vector3 curPosition = transform.position; curPosition.z = 0; path.Add(curPosition); // do linear optimization to the path Vector3 lastStartPoint = curPosition; Vector3 lastEndPoint = newPath[0].position; bool canSkip = true; for (int i = 1; i < newPath.Count; i++) { canSkip = true; RaycastHit2D hit = Physics2D.Linecast(lastStartPoint + (newPath [i].position - lastStartPoint).normalized * customBoundOffset, newPath [i].position); if (hit.transform != null) { if (hit.transform.gameObject == gameObject) { RaycastHit2D[] targetPoint = Physics2D.LinecastAll(lastStartPoint + (newPath [i].position - lastStartPoint).normalized * customBoundOffset, newPath [i].position); int j = 0; for (j = 0; j < targetPoint.Length; j++) { if (targetPoint [j].transform != null && targetPoint [j].transform.gameObject.GetComponent <NavMesh2DObstacle> () != null) { canSkip = false; break; } } } else if (hit.transform.gameObject.GetComponent <NavMesh2DObstacle> () != null) { canSkip = false; } } if (canSkip) { lastEndPoint = newPath [i].position; } else { path.Add(lastEndPoint); lastStartPoint = newPath [i].position; } // Debug.Log ("Path point " + i + " is (" + newPath [i].position.x + ", " + newPath [i].position.y + ")."); } if (!path.Contains(lastEndPoint)) { path.Add(lastEndPoint); } path.Add(target); if (!UpdateManager.IsRegistered(this)) { UpdateManager.RegisterFixedUpdate(this); } } }