//Call this function to start calculating a path public AstarPath.Path StartPath(Vector3 start, Vector3 end) { //Cancel the previous path if (path != null) { path.error = true; } endpos = end; startpos = start; //Shall we search all grids or only the one specified in the "grid" variable if (gridSelection == GridSelection.Auto) { path = new AstarPath.Path(this, start, end, maxAngle, angleCost, stepByStep); //Create a new Path instance } else { path = new AstarPath.Path(this, start, end, maxAngle, angleCost, stepByStep, grid); //Create a new Path instance } isDone = false; /*if (multithread) { * AstarPath.StartPathPreThread(path,this); * StartCoroutine (MultithreadingCompleteCheck ()); * } else {*/ AstarPath.StartPath(path); //Send a call to the pathfinding system to calculate the path //} return(path); }
//Check if the path is finnished, see OnCompleteLater /*public IEnumerator MultithreadingCompleteCheck () { * while (!isComplete) { * yield return 0; * } * isDone = false; * OnComplete (path); * } * * //This is called instaed of OnComplete when using multithreading. Other thread can't call Unity specific stuff, so we have to set a flag that the path is finnished and then call OnComplete next time we check if it is complete (in Update). * public void OnCompleteLater (AstarPath.Path p) { * * if (path != p) { * return; * } * * isComplete = true; * }*/ //This function will be called when the pathfinding is complete, it will be called when the pathfinding returned an error too. public void OnComplete(AstarPath.Path p) { //If the script was already calculating a path when a new path started calculating, then it would have canceled the first path, that will generate an OnComplete message from the first path, this makes sure we only get OnComplete messages from the path we started calculating latest. if (path != p) { return; } isDone = true; //What should we do if the path returned an error (there is no available path to the target). if (path.error) { switch (onError) { case OnError.None: return; case OnError.ErrorMessage: SendMessage("PathError", SendMessageOptions.DontRequireReceiver); break; case OnError.EmptyArray: SendMessage("PathComplete", new Vector3[0], SendMessageOptions.DontRequireReceiver); break; } return; } if (path.path == null) { Debug.LogError("The 'Path' array is not assigned - System Error - Please send a bug report - Include the following info:\nError = " + p.error + "\nStart = " + startpos + "\nEnd = " + endpos + "\nFound End = " + p.foundEnd + "\nError = " + p.error); } //Still at beta stage, can crash the game //if (postProcessEdges) { //Vector3[] points = AstarProcess.PostProcess.NavigationMesh (p.path,AstarPath.active.meshNodePosition == MeshNodePosition.Edge, startpos, endpos,turningRadius); //(FindObjectOfType (typeof(Clicker)) as Clicker).NavigationMesh (p.path,AstarPath.active.meshNodePosition == MeshNodePosition.Edge, startpos, endpos,turningRadius); //} if (path.path.Length > 1) { //Convert the Node array to a Vector3 array, subract one from the array if Remove First is true and add one to the array if Use Real End is set to Add Vector3[] a = new Vector3[path.path.Length - (removeFirst ? 1 : 0) + (endPoint == RealEnd.AddExact && !path.forceEndSnap ? 1 : 0)]; for (int i = 0; i < path.path.Length; i++) { //Ignore the first node if Remove First is set to True if (removeFirst && i == 0) { continue; } a[i - (removeFirst ? 1 : 0)] = path.path[i].vectorPos; } if (startPoint == RealStart.Exact && !path.forceStartSnap) { a[0] = startpos; } //Assign the endpoint if ((endPoint == RealEnd.AddExact || endPoint == RealEnd.Exact) && !path.forceEndSnap) { a[a.Length - 1] = endpos; } //Store the path in a variable so it can be drawn in the scene view for debugging pathPoints = a; //Post-process the path using splines if the user has choosen to do that (default is None) switch (postProcessor) { case PostProcessor.CubicBezier: pathPoints = PostProcessSplines.CubicSmooth(pathPoints, subdivisions, bezierNormalizeTangents, bezierTangentLength); break; case PostProcessor.CatmullRom: pathPoints = PostProcessSplines.CatmullRom(pathPoints, subdivisions); break; case PostProcessor.SimpleSmooth: pathPoints = PostProcessSplines.SimpleSmooth(pathPoints, simpleSmoothIterations, simpleSmoothStrength, subdivisions); break; } //Send the Vector3 array to a movement script attached to this gameObject SendMessage("PathComplete", pathPoints, SendMessageOptions.DontRequireReceiver); } else { Vector3[] a2 = new Vector3[1] { ((endPoint == RealEnd.AddExact || endPoint == RealEnd.Exact) && !path.forceEndSnap ? endpos : startpos) }; pathPoints = a2; SendMessage("PathComplete", a2, SendMessageOptions.DontRequireReceiver); } }
public virtual void Open(AstarPath.BinaryHeap open, AstarPath.Path p, Node start, Node end, float angleCost) { for (int i = 0; i < enabledConnections.Length; i++) { Connection connection = enabledConnections[i]; Node node = connection.endNode; if (node == start) { continue; } //Debug.DrawLine (current.vectorPos,current.neighbours[i].vectorPos,Color.red); //Uncomment for debug //If the nodes script variable isn't refering to this path class the node counts as "not used yet" and can then be used if (node.script != p) { //Test if the angle from the current node to this one has exceded the angle limit //if (angle >= maxAngle) { // return; //} node.parent = this; node.script = p; node.basicCost = connection.cost + Mathf.RoundToInt(connection.cost * connection.angle * angleCost); //(current.costs == null || costs.Length == 0 ? costs[node.invParentDirection] : current.costs[node.invParentDirection]); //Calculate the extra cost of moving in a slope //node.extraCost = ; //Add the node to the open array //Debug.DrawLine (current.vectorPos,current.neighbours[i].vectorPos,Color.green); //Uncomment for @Debug node.UpdateH(end); node.UpdateG(); open.Add(node); } else { //If not we can test if the path from the current node to this one is a better one then the one already used int cost2 = connection.cost + Mathf.RoundToInt(connection.cost * connection.angle * angleCost); //(current.costs == null || current.costs.Length == 0 ? costs[current.neighboursKeys[i]] : current.costs[current.neighboursKeys[i]]); //int extraCost2 if (g + cost2 + node.penalty < node.g) { node.basicCost = cost2; //node.extraCost = extraCost2; node.parent = this; node.UpdateAllG(); open.Add(node); //@Quality, uncomment for better quality (I think). //Debug.DrawLine (current.vectorPos,current.neighbours[i].vectorPos,Color.cyan); //Uncomment for @Debug } else if (node.g + cost2 + penalty < g) //Or if the path from this node ("node") to the current ("current") is better { bool contains = false; //Make sure we don't travel along the wrong direction of a one way link now, make sure the Current node can be accesed from the Node. for (int y = 0; y < node.connections.Length; y++) { if (node.connections[y].endNode == this) { contains = true; break; } } if (!contains) { continue; } parent = node; basicCost = cost2; //extraCost = extraCost2; node.UpdateAllG(); //Debug.DrawLine (current.vectorPos,current.neighbours[i].vectorPos,Color.blue); //Uncomment for @Debug open.Add(this); } } } }
//Call this function to start calculating a path public AstarPath.Path StartPath (Vector3 start, Vector3 end) { //Cancel the previous path if (path != null) { path.error = true; //StopCoroutine ("PathUpdate"); } endpos = end; startpos = start; //SendMessage("Stop",SendMessageOptions.DontRequireReceiver);//This will make the player stop //Shall we search all grids or only the one specified in the "grid" variable if (gridSelection == GridSelection.Auto) { path = new AstarPath.Path (start,end,maxAngle,angleCost,stepByStep);//Create a new Path instance } else { path = new AstarPath.Path (start,end,maxAngle,angleCost,stepByStep,grid);//Create a new Path instance } StartCoroutine (AstarPath.StartPathYield (path,this));//Start a coroutine (function including yields) to calculate the path return path; }
//Call this function to start calculating a path public AstarPath.Path StartPath (Vector3 start, Vector3 end) { //Cancel the previous path if (path != null) { path.error = true; } endpos = end; startpos = start; //Shall we search all grids or only the one specified in the "grid" variable if (gridSelection == GridSelection.Auto) { path = new AstarPath.Path (this,start,end,maxAngle,angleCost,stepByStep);//Create a new Path instance } else { path = new AstarPath.Path (this,start,end,maxAngle,angleCost,stepByStep,grid);//Create a new Path instance } isDone = false; /*if (multithread) { AstarPath.StartPathPreThread(path,this); StartCoroutine (MultithreadingCompleteCheck ()); } else {*/ AstarPath.StartPath(path);//Send a call to the pathfinding system to calculate the path //} return path; }