//~ public List<Node> GetNeighbouringNode(Node origin, Node node, int iteration){ //~ float gridSize=Node.GetGridSize(); //~ List<Node> nodeList=new List<Node>(); //~ foreach(Node node in node.neighbourNode){ //~ if(Vector3.Distance(node.pos, origin.pos)<gridSize*1.5f){ //~ nodeList.Add(node); //~ } //~ } //~ } //make cause system to slow down, use with care static public List <Vector3> ForceSearch(NodeTD startN, NodeTD endN, NodeTD blockN, NodeTD[] graph, int footprint) { if (blockN != null) { blockN.walkable = false; //Debug.Log("block reference node"); List <NodeTD> tempList = GetNodeInFootprint(blockN, footprint); //Debug.Log(footprint+" "+tempList.Count); foreach (NodeTD node in tempList) { node.walkable = false; } } bool pathFound = true; int searchCounter = 0; //used to count the total amount of node that has been searched List <NodeTD> closeList = new List <NodeTD>(); NodeTD[] openList = new NodeTD[graph.Length]; List <int> openListRemoved = new List <int>(); int openListCounter = 0; NodeTD currentNode = startN; float currentLowestF = Mathf.Infinity; int id = 0; //use element num of the node with lowest score in the openlist during the comparison process int i = 0; //universal int value used for various looping operation while (true) { if (currentNode == endN) { break; } closeList.Add(currentNode); currentNode.listState = _ListStateTD.Close; currentNode.ProcessNeighbour(endN); foreach (NodeTD neighbour in currentNode.neighbourNode) { if (neighbour.listState == _ListStateTD.Unassigned && neighbour.walkable) { neighbour.listState = _ListStateTD.Open; if (openListRemoved.Count > 0) { openList[openListRemoved[0]] = neighbour; openListRemoved.RemoveAt(0); } else { openList[openListCounter] = neighbour; openListCounter += 1; } } } currentNode = null; currentLowestF = Mathf.Infinity; id = 0; for (i = 0; i < openListCounter; i++) { if (openList[i] != null) { if (openList[i].scoreF < currentLowestF) { currentLowestF = openList[i].scoreF; currentNode = openList[i]; id = i; } } } if (currentNode == null) { pathFound = false; break; } openList[id] = null; openListRemoved.Add(id); searchCounter += 1; } //~ float timeUsed=Time.realtimeSinceStartup-timeStart; //~ if(pathFound) Debug.Log("Path found. Searched "+searchCounter+" nodes, used "+timeUsed+"seconds"); //~ else Debug.Log("no path. Searched "+searchCounter+" nodes, used "+timeUsed+"seconds"); List <Vector3> p = new List <Vector3>(); if (pathFound) { while (currentNode != null) { p.Add(currentNode.pos); currentNode = currentNode.parent; } p = InvertArray(p); //if(pathFinder.pathSmoothing) { // p=pathFinder.LOSPathSmoothingBackward(p); // p=pathFinder.LOSPathSmoothingForward(p); //} } if (blockN != null) { blockN.walkable = true; //Debug.Log("unblock reference node"); List <NodeTD> tempList = GetNodeInFootprint(blockN, footprint); foreach (NodeTD node in tempList) { node.walkable = true; } } ResetGraph(graph); return(p); }
IEnumerator _Search(NodeTD startN, NodeTD endN, NodeTD blockN, NodeTD[] graph, SetPathCallbackTD callBackFunc) { //~ foreach(NodeTD nn in graph){ //~ DebugDrawTD.Cross(nn.pos, nn.walkable!=true ? Color.red : Color.white, 6); //~ DebugDrawTD.Square(nn.pos, nn.neighbourNode==null ? Color.red : Color.white, 6); //~ } //block node is for checking if a path exist if that particular node is block if (blockN != null) { //var switched:boolean=true; //if(block.walkable) block.walkable=false; //else switched=false; blockN.walkable = false; } //time tracker for performance check float timeStart = Time.realtimeSinceStartup; //mark that a serac has started, any further query will be queued searching = true; bool pathFound = true; int searchCounter = 0; //used to count the total amount of node that has been searched int loopCounter = 0; //used to count how many node has been search in the loop, if it exceed a value, bring it to the next frame //float LoopTime=Time.realtimeSinceStartup; //closelist, used to store all the node that are on the path List <NodeTD> closeList = new List <NodeTD>(); //openlist, all the possible node that yet to be on the path, the number can only be as much as the number of node in the garph NodeTD[] openList = new NodeTD[graph.Length]; //an array use to record the element number in the open list which is empty after the node is removed to be use as currentNode, //so we can use builtin array with fixed length for openlist, also we can loop for the minimal amount of node in every search List <int> openListRemoved = new List <int>(); //current count of elements that are occupied in openlist, openlist[n>openListCounter] are null int openListCounter = 0; //set start as currentNode NodeTD currentNode = startN; //use to compare node in the openlist has the lowest score, alwyas set to Infinity when not in used float currentLowestF = Mathf.Infinity; int id = 0; //use element num of the node with lowest score in the openlist during the comparison process int i = 0; //universal int value used for various looping operation //loop start while (true) { //if we have reach the destination if (currentNode == endN) { break; } //for gizmo debug purpose //currentNodeBeingProcess=currentNode; //move currentNode to closeList; closeList.Add(currentNode); currentNode.listState = _ListStateTD.Close; //loop through the neighbour of current loop, calculate score and stuff currentNode.ProcessNeighbour(endN); //put all neighbour in openlist foreach (NodeTD neighbour in currentNode.neighbourNode) { if (neighbour.listState == _ListStateTD.Unassigned && neighbour.walkable) { //set the node state to open neighbour.listState = _ListStateTD.Open; //if there's an open space in openlist, fill the space if (openListRemoved.Count > 0) { openList[openListRemoved[0]] = neighbour; //remove the number from openListRemoved since this element has now been occupied openListRemoved.RemoveAt(0); } //else just stack on it and increase the occupication counter else { openList[openListCounter] = neighbour; openListCounter += 1; } } } //clear the current node, before getting a new one, so we know if there isnt any suitable next node currentNode = null; //get the next point from openlist, set it as current point //just loop through the openlist until we reach the maximum occupication //while that, get the node with the lowest score currentLowestF = Mathf.Infinity; id = 0; for (i = 0; i < openListCounter; i++) { if (openList[i] != null) { if (openList[i].scoreF < currentLowestF) { currentLowestF = openList[i].scoreF; currentNode = openList[i]; id = i; } } } //if there's no node left in openlist, path doesnt exist if (currentNode == null) { pathFound = false; break; } //remove the new currentNode from openlist openList[id] = null; //put the id into openListRemoved so we know there's an empty element that can be filled in the next loop openListRemoved.Add(id); //increase the counter searchCounter += 1; loopCounter += 1; //if exceed the search limit per frame, bring the search to the next frame if (loopCounter > ScanNodeLimitPerFrame) { loopCounter = 0; //reset the loopCounter for the next frame yield return(null); } } //see how long it has taken to complete the search //float timeUsed=Time.realtimeSinceStartup-timeStart; //if(pathFound) Debug.Log("Path found. Searched "+searchCounter+" nodes, used "+timeUsed+"seconds"); //else Debug.Log("no path. Searched "+searchCounter+" nodes, used "+timeUsed+"seconds"); //trace back the path through closeList List <Vector3> p = new List <Vector3>(); if (pathFound) { //track back the node's parent to form a path while (currentNode != null) { p.Add(currentNode.pos); currentNode = currentNode.parent; } //since the path is now tracked from endN ot startN, invert the list p = InvertArray(p); //~ if(pathSmoothing) { //~ //Debug.Log("smoothing path"); //~ p=LOSPathSmoothingBackward(p); //~ p=LOSPathSmoothingForward(p); //~ } if (pathSmoothing == _PathSmoothing.Mean) { p = MeanSmoothPath(p); } else if (pathSmoothing == _PathSmoothing.LOS) { p = LOSPathSmoothingBackward(p); p = LOSPathSmoothingForward(p); } //else Debug.Log("skip smoothing path"); } //~ else Debug.Log("no path found"); //if this is just to check if a path is blocked, now we can clear the assumed blocked node if (blockN != null) { blockN.walkable = true; } callBackFunc(p); //reset the all the nodegraph's node state? //Reset(); //clear searching so indicate the search has end and a new serach can be called searching = false; ResetGraph(graph); }