public static void PreBuildTower(UnitTower tower) { BuildPlatform platform = null; LayerMask mask = 1 << TDTK.GetLayerPlatform(); Collider[] cols = Physics.OverlapSphere(tower.GetPos(), GetGridSize(), mask); if (cols.Length > 0) { platform = cols[0].gameObject.GetComponent <BuildPlatform>(); } if (platform != null) { NodeTD node = platform.GetNearestNode(tower.GetPos()); if (Vector3.Distance(node.pos, tower.GetPos()) < GetGridSize()) { AddTower(tower, platform, node.ID); tower.transform.position = node.pos; return; } } //~ GameObject obj=new GameObject("platform"); //~ SphereCollider collider=obj.AddComponent<SphereCollider>(); //~ collider.radius=GetGridSize()*.5f; //~ obj.transform.parent=tower.transform; //~ obj.transform.localPosition=Vector3.zero; //~ obj.layer=TDTK.GetLayerPlatform(); //~ platform=obj.AddComponent<BuildPlatform>(); //~ platform.SingleNodePlatform(); AddTower(tower, CreatePlatformForTower(tower, GetGridSize()), 0); }
public SearchQueue(NodeTD n1, NodeTD n2, NodeTD[] g, SetPathCallbackTD func) { startNode = n1; endNode = n2; graph = g; callBackFunc = func; }
public int GetUnitNearestNodeID(UnitCreep unit) { NodeTD n1 = platform.GetNearestNode(unit.GetTargetPos(), 1); //get walkable only NodeTD n2 = platform.GetNearestNode(unit.GetLastTargetPos(), 1); return((Vector3.Distance(unit.GetPos(), n1.pos) > Vector3.Distance(unit.GetPos(), n2.pos)) ? n2.ID : n1.ID); }
public static NodeTD GetNearestNode(Vector3 point, NodeTD[] graph, int searchMode){ float dist=Mathf.Infinity; float currentNearest=Mathf.Infinity; NodeTD nearestNode=null; foreach(NodeTD node in graph){ if(searchMode==0){ dist=Vector3.Distance(point, node.pos); if(dist<currentNearest){ currentNearest=dist; nearestNode=node; } } else if(searchMode==1){ if(node.walkable){ dist=Vector3.Distance(point, node.pos); if(dist<currentNearest){ currentNearest=dist; nearestNode=node; } } } else if(searchMode==2){ if(!node.walkable){ dist=Vector3.Distance(point, node.pos); if(dist<currentNearest){ currentNearest=dist; nearestNode=node; } } } } return nearestNode; }
public bool CheckForBlock(Vector3 pos) { float gridSize = BuildManager.GetGridSize(); NodeTD targetNode = PathFinder.GetNearestNode(pos, nodeGraph); for (int i = 0; i < subPathList.Count; i++) { SubPath subPath = subPathList[i]; if (Vector3.Distance(pos, subPath.startN.pos) < gridSize / 2) { return(true); } if (Vector3.Distance(pos, subPath.endN.pos) < gridSize / 2) { return(true); } if (subPath.IsNodeInPath(targetNode)) { subPath.altPath = PathFinder.ForceSearch(subPath.startN, subPath.endN, targetNode, nodeGraph); if (subPath.altPath.Count == 0) { return(true); } } } nextBuildNode = targetNode; return(false); }
public static void GetPath(NodeTD startN, NodeTD endN, NodeTD[] graph, SetPathCallbackTD callBackFunc) { if (instance == null) { Init(); } instance._GetPath(startN, endN, graph, callBackFunc); }
public bool IsNodeInPath(NodeTD node){ float gridSize=BuildManager.GetGridSize(); for(int i=0; i<path.Count; i++){ float dist=Vector3.Distance(node.pos, path[i]); if(dist<gridSize*.85f) return true; } return false; }
public void UnbuildTower(NodeTD node) { node.walkable = true; for (int i = 0; i < subPathList.Count; i++) { subPathList[i].SearchNewPath(nodeGraph); } }
public List<Vector3> altPath=new List<Vector3>(); //for checking if there's any block public void Init(PlatformTD platform){ parentPlatform=platform; startN=PathFinder.GetNearestNode(connectStart.position, platform.GetNodeGraph()); endN=PathFinder.GetNearestNode(connectEnd.position, platform.GetNodeGraph()); path.Add((connectStart.position+connectEnd.position)/2); SearchNewPath(platform.GetNodeGraph()); }
public List <Vector3> altPath = new List <Vector3>(); //for checking if there's any block public void Init(PlatformTD platform) { parentPlatform = platform; startN = PathFinder.GetNearestNode(connectStart.position, platform.GetNodeGraph()); endN = PathFinder.GetNearestNode(connectEnd.position, platform.GetNodeGraph()); path.Add((connectStart.position + connectEnd.position) / 2); SearchNewPath(platform.GetNodeGraph()); }
public void _GetPath(NodeTD startN, NodeTD endN, NodeTD[] graph, SetPathCallbackTD callBackFunc) { if (!searching) { //commence search StartCoroutine(_SearchRoutine(startN, endN, graph, callBackFunc)); } else { //if a serach is in progress, put current request into the queue list SearchQueue q = new SearchQueue(startN, endN, graph, callBackFunc); searchQueueList.Add(q); } }
public bool IsNodeInPath(NodeTD node) { float gridSize = BuildManager.GetGridSize(); for (int i = 0; i < path.Count; i++) { float dist = Vector3.Distance(node.pos, path[i]); if (dist < gridSize * .85f) { return(true); } } return(false); }
//searchMode: 0-any node, 1-walkable only, 2-unwalkable only //public static NodeTD GetNearestNode(Vector3 point, NodeTD[] graph){ return GetNearestNode(point, graph, 0); } public static NodeTD GetNearestNode(Vector3 point, NodeTD[] graph, int searchMode = 0) { float dist = Mathf.Infinity; float currentNearest = Mathf.Infinity; NodeTD nearestNode = null; if (searchMode == 0) { foreach (NodeTD node in graph) { dist = Vector3.Distance(point, node.pos); if (dist < currentNearest) { currentNearest = dist; nearestNode = node; } } } else if (searchMode == 1) { foreach (NodeTD node in graph) { if (!node.IsWalkable()) { continue; } dist = Vector3.Distance(point, node.pos); if (dist < currentNearest) { currentNearest = dist; nearestNode = node; } } } else if (searchMode == 2) { foreach (NodeTD node in graph) { if (node.IsWalkable()) { continue; } dist = Vector3.Distance(point, node.pos); if (dist < currentNearest) { currentNearest = dist; nearestNode = node; } } } return(nearestNode); }
void ResetSubPath(SubPath platformSubPath) { if (dummyT == null) { dummyT = new GameObject().transform; } Quaternion rot = Quaternion.LookRotation(subPath[subWaypointID] - thisT.position); dummyT.rotation = rot; dummyT.position = thisT.position; Vector3 pos = dummyT.TransformPoint(0, 0, BuildManager.GetGridSize() / 2); NodeTD startN = PathFinder.GetNearestNode(pos, platformSubPath.parentPlatform.GetNodeGraph()); PathFinder.GetPath(startN, platformSubPath.endN, platformSubPath.parentPlatform.GetNodeGraph(), this.SetSubPath); }
public static void BuildTower(UnitTower prefab, BuildPlatform platform, int nodeID, bool useRsc = true) { Debug.Log("BuildTower " + prefab); if (useRsc) { if (!RscManager.HasSufficientRsc(prefab.GetCost())) { Debug.Log("Insufficient resources"); return; } Debug.Log("Get cost " + prefab.GetCost()[0]); RscManager.SpendRsc(prefab.GetCost()); } NodeTD node = platform.GetNode(nodeID); GameObject obj = (GameObject)Instantiate(prefab.gameObject, node.pos, platform.GetRot() * Quaternion.Euler(-90, 0, 0)); UnitTower tower = obj.GetComponent <UnitTower>(); AddTower(tower, platform, nodeID); }
public void BuildTower(Vector3 pos, UnitTower tower) { //pathfinding related code, only call if this platform is walkable; if (!walkable) { return; } if (tower.type != _TowerType.Mine) { NodeTD node = PathFinder.GetNearestNode(pos, nodeGraph); node.walkable = false; tower.SetPlatform(this, node); //if the node has been check before during CheckForBlock(), just use the altPath if (node == nextBuildNode) { for (int i = 0; i < subPathList.Count; i++) { if (subPathList[i].IsNodeInPath(node)) { subPathList[i].SwitchToSubPath(); } } return; } for (int i = 0; i < subPathList.Count; i++) { if (subPathList[i].IsNodeInPath(node)) { subPathList[i].SearchNewPath(nodeGraph); } } } }
public void SetPlatform(PlatformTD platform, NodeTD node) { occupiedPlatform = platform; occupiedNode = node; }
public void SearchNewPath(NodeTD[] nodeGraph){ PathFinder.GetPath(startN, endN, nodeGraph, this.SetPath); }
public static void GetPath(NodeTD startN, NodeTD endN, NodeTD[] graph, SetPathCallbackTD callBackFunc) { if(instance==null) Init(); instance._GetPath(startN, endN, graph, callBackFunc); }
public void ProcessNeighbour(NodeTD node) { ProcessNeighbour(node.pos); }
IEnumerator _SearchRoutine(NodeTD startN, NodeTD endN, NodeTD[] graph, SetPathCallbackTD callBackFunc) { //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); } } //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); p = SmoothPath(p); } callBackFunc(p); //clear searching so indicate the search has end and a new serach can be called searching = false; ResetGraph(graph); }
public static NodeTD[] GenerateNode(PlatformTD platform, float heightOffset){ if(instance==null) Init(); Transform platformT=platform.thisT; float gridSize=BuildManager.GetGridSize(); float scaleX=platform.thisT.localScale.x; float scaleZ=platform.thisT.localScale.z; int countX=(int)(scaleX/gridSize); int countZ=(int)(scaleZ/gridSize); float x=-scaleX/2/scaleX; float z=-scaleZ/2/scaleZ; Vector3 point=platformT.TransformPoint(new Vector3(x, 0, z)); thisT.position=point; thisT.rotation=platformT.rotation; thisT.position=thisT.TransformPoint(new Vector3(gridSize/2, heightOffset, gridSize/2)); NodeTD[] nodeGraph=new NodeTD[countZ*countX]; int counter=0; for(int i=0; i<countZ; i++){ for(int j=0; j<countX; j++){ Vector3 pos=thisT.position; pos.y=pos.y+5000; LayerMask mask=1<<LayerManager.LayerTower(); RaycastHit hit1; if(Physics.Raycast(pos, Vector3.down, out hit1, Mathf.Infinity, ~mask)) { nodeGraph[counter]=new NodeTD(new Vector3(pos.x, hit1.point.y+heightOffset, pos.z), counter); } else{ nodeGraph[counter]=new NodeTD(pos, counter); nodeGraph[counter].walkable=false; } counter+=1; thisT.position=thisT.TransformPoint(new Vector3(gridSize, 0, 0)); } thisT.position=thisT.TransformPoint(new Vector3(-(countX)*gridSize, 0, gridSize)); } thisT.position=Vector3.zero; thisT.rotation=Quaternion.identity; counter=0; foreach(NodeTD cNode in nodeGraph){ if(cNode.walkable){ //check if there's anything within the point LayerMask mask=1<<LayerManager.LayerPlatform(); mask|=1<<LayerManager.LayerTower(); if(LayerManager.LayerTerrain()>=0) mask|=1<<LayerManager.LayerTerrain(); Collider[] cols=Physics.OverlapSphere(cNode.pos, gridSize*0.45f, ~mask); if(cols.Length>0){ cNode.walkable=false; counter+=1; } } } float neighbourDistance=0; float neighbourRange; if(instance.connectDiagonalNeighbour) neighbourRange=gridSize*1.5f; else neighbourRange=gridSize*1.1f; counter=0; //assign the neighouring node for each node in the grid foreach(NodeTD currentNode in nodeGraph){ //only if that node is walkable if(currentNode.walkable){ //create an empty array List<NodeTD> neighbourNodeList=new List<NodeTD>(); List<float> neighbourCostList=new List<float>(); NodeTD[] neighbour=new NodeTD[8]; int id=currentNode.ID; if(id>countX-1 && id<countX*countZ-countX){ //print("middle rows"); if(id!=countX) neighbour[0]=nodeGraph[id-countX-1]; neighbour[1]=nodeGraph[id-countX]; neighbour[2]=nodeGraph[id-countX+1]; neighbour[3]=nodeGraph[id-1]; neighbour[4]=nodeGraph[id+1]; neighbour[5]=nodeGraph[id+countX-1]; neighbour[6]=nodeGraph[id+countX]; if(id!=countX*countZ-countX-1)neighbour[7]=nodeGraph[id+countX+1]; } else if(id<=countX-1){ //print("first row"); if(id!=0) neighbour[0]=nodeGraph[id-1]; if(nodeGraph.Length>id+1) neighbour[1]=nodeGraph[id+1]; if(countZ>0){ if(nodeGraph.Length>id+countX-1) neighbour[2]=nodeGraph[id+countX-1]; if(nodeGraph.Length>id+countX) neighbour[3]=nodeGraph[id+countX]; if(nodeGraph.Length>id+countX+1) neighbour[4]=nodeGraph[id+countX+1]; } } else if(id>=countX*countZ-countX){ //print("last row"); neighbour[0]=nodeGraph[id-1]; if(id!=countX*countZ-1) neighbour[1]=nodeGraph[id+1]; if(id!=countX*(countZ-1))neighbour[2]=nodeGraph[id-countX-1]; neighbour[3]=nodeGraph[id-countX]; neighbour[4]=nodeGraph[id-countX+1]; } //scan through all the node in the grid foreach(NodeTD node in neighbour){ //if this the node is not currentNode if(node!=null && node.walkable){ //if this node is within neighbour node range neighbourDistance=GetHorizontalDistance(currentNode.pos, node.pos); if(neighbourDistance<neighbourRange){ //if nothing's in the way between these two LayerMask mask=1<<LayerManager.LayerPlatform(); mask|=1<<LayerManager.LayerTower(); if(!Physics.Linecast(currentNode.pos, node.pos, ~mask)){ //if the slop is not too steep //if(Mathf.Abs(GetSlope(currentNode.pos, node.pos))<=maxSlope){ //add to list //if(!node.walkable) Debug.Log("error"); neighbourNodeList.Add(node); neighbourCostList.Add(neighbourDistance); //}//else print("too steep"); }//else print("something's in the way"); }//else print("out of range "+neighbourDistance); }//else print("unwalkable"); } //set the list as the node neighbours array currentNode.SetNeighbour(neighbourNodeList, neighbourCostList); //if(neighbourNodeList.Count==0) //Debug.Log("no heighbour. node number "+counter+" "+neighbourNodeList.Count); } counter+=1; } return nodeGraph; }
//make cause system to slow down, use with care public static List <Vector3> ForceSearch(NodeTD startN, NodeTD endN, NodeTD blockN, NodeTD[] graph, int footprint = -1) { if (blockN != null) { blockN.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; } List <Vector3> p = new List <Vector3>(); if (pathFound) { while (currentNode != null) { p.Add(currentNode.pos); currentNode = currentNode.parent; } p = InvertArray(p); p = SmoothPath(p); } if (blockN != null) { blockN.walkable = true; } ResetGraph(graph); return(p); }
//make cause system to slow down, use with care public static List<Vector3> ForceSearch(NodeTD startN, NodeTD endN, NodeTD blockN, NodeTD[] graph, int footprint=-1) { if(blockN!=null) blockN.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; } List<Vector3> p=new List<Vector3>(); if(pathFound){ while(currentNode!=null){ p.Add(currentNode.pos); currentNode=currentNode.parent; } p=InvertArray(p); p=SmoothPath(p); } if(blockN!=null)blockN.walkable=true; ResetGraph(graph); return p; }
IEnumerator _SearchRoutine(NodeTD startN, NodeTD endN, NodeTD[] graph, SetPathCallbackTD callBackFunc) { //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; } } //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); p=SmoothPath(p); } callBackFunc(p); //clear searching so indicate the search has end and a new serach can be called searching=false; ResetGraph(graph); }
public void _GetPath(NodeTD startN, NodeTD endN, NodeTD[] graph, SetPathCallbackTD callBackFunc) { if(!searching){ //commence search StartCoroutine(_SearchRoutine(startN, endN, graph, callBackFunc)); } else{ //if a serach is in progress, put current request into the queue list SearchQueue q=new SearchQueue(startN, endN, graph, callBackFunc); searchQueueList.Add(q); } }
public static void ResetGraph(NodeTD[] nodeGraph) { foreach(NodeTD node in nodeGraph){ node.listState=_ListStateTD.Unassigned; node.parent=null; } }
//make cause system to slow down, use with care public static List <Vector3> Search(NodeTD startN, NodeTD endN, NodeTD[] graph, NodeTD blockN = null, int footprint = -1) { Init(); if (startN.IsBlocked()) { return(new List <Vector3>()); } if (blockN != null) { blockN.SetWalkable(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.IsBlocked()) { 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; } List <Vector3> p = new List <Vector3>(); if (pathFound) { if (EnablePathSmoothing()) { List <NodeTD> pn = new List <NodeTD>(); while (currentNode != null) { pn.Add(currentNode); currentNode = currentNode.parent; } //for(int n=0; n<pn.Count; n++) Debug.DrawLine(pn[n].GetPos(), pn[n].GetPos()+new Vector3(0, .5f, 0), Color.white, .5f); pn = PathSmoothing(pn); for (int n = 0; n < pn.Count; n++) { p.Add(pn[n].GetPos()); } //for(int n=0; n<pn.Count; n++) Debug.DrawLine(pn[n].GetPos(), pn[n].GetPos()+new Vector3(0, .25f, 0), Color.red, .5f); } else { while (currentNode != null) { p.Add(currentNode.pos); currentNode = currentNode.parent; } } p.Reverse(); } if (blockN != null) { blockN.SetWalkable(true); } ResetGraph(graph); return(p); }
public static NodeTD[] GenerateNode(BuildPlatform platform, float gridSize = 1, float heightOffset = 0) { if (refT == null) { refT = new GameObject("RefT").transform; refT.parent = TowerManager.GetInstance().transform; } Transform platformT = platform.transform; float scaleX = platformT.localScale.x; float scaleZ = platformT.localScale.y; int countX = (int)(scaleX / gridSize); int countZ = (int)(scaleZ / gridSize); float x = -scaleX / 2 / scaleX; float z = -scaleZ / 2 / scaleZ; Vector3 point = platformT.TransformPoint(new Vector3(x, z, 0)); refT.position = point; refT.rotation = platformT.rotation * Quaternion.Euler(-90, 0, 0); refT.position = refT.TransformPoint(new Vector3(gridSize / 2, heightOffset, gridSize / 2)); NodeTD[] nodeGraph = new NodeTD[countZ * countX]; int counter = 0; for (int i = 0; i < countZ; i++) { for (int j = 0; j < countX; j++) { nodeGraph[counter] = new NodeTD(refT.position, counter); counter += 1; refT.position = refT.TransformPoint(new Vector3(gridSize, 0, 0)); } refT.position = refT.TransformPoint(new Vector3(-(countX) * gridSize, 0, gridSize)); } refT.position = Vector3.zero; refT.rotation = Quaternion.identity; LayerMask mask = 1 << TDTK.GetLayerPlatform() | 1 << TDTK.GetLayerTower() | 1 << TDTK.GetLayerTerrain() | 1 << TDTK.GetLayerNoBuild(); LayerMask maskTowerBlock = 1 << TDTK.GetLayerNoBuild(); counter = 0; foreach (NodeTD cNode in nodeGraph) { //check if there's anything within the point Collider[] cols = Physics.OverlapSphere(cNode.pos, gridSize * 0.45f, ~mask); if (cols.Length > 0) { cNode.SetWalkable(false); counter += 1; } cols = Physics.OverlapSphere(cNode.pos, gridSize * 0.45f, maskTowerBlock); if (cols.Length > 0) { cNode.SetBlockedForTower(true); } } float neighbourDistance = 0; float neighbourRange = gridSize * 1.1f; //if(instance.connectDiagonalNeighbour) neighbourRange=gridSize*1.5f; //else neighbourRange=gridSize*1.1f; counter = 0; //assign the neighouring node for each node in the grid foreach (NodeTD currentNode in nodeGraph) { //only if that node is walkable if (currentNode.IsWalkable()) { //create an empty array List <NodeTD> neighbourNodeList = new List <NodeTD>(); List <float> neighbourCostList = new List <float>(); NodeTD[] neighbour = new NodeTD[8]; int id = currentNode.ID; if (id > countX - 1 && id < countX * countZ - countX) { //print("middle rows"); if (id != countX) { neighbour[0] = nodeGraph[id - countX - 1]; } neighbour[1] = nodeGraph[id - countX]; neighbour[2] = nodeGraph[id - countX + 1]; neighbour[3] = nodeGraph[id - 1]; neighbour[4] = nodeGraph[id + 1]; neighbour[5] = nodeGraph[id + countX - 1]; neighbour[6] = nodeGraph[id + countX]; if (id != countX * countZ - countX - 1) { neighbour[7] = nodeGraph[id + countX + 1]; } } else if (id <= countX - 1) { //print("first row"); if (id != 0) { neighbour[0] = nodeGraph[id - 1]; } if (nodeGraph.Length > id + 1) { neighbour[1] = nodeGraph[id + 1]; } if (countZ > 0) { if (nodeGraph.Length > id + countX - 1) { neighbour[2] = nodeGraph[id + countX - 1]; } if (nodeGraph.Length > id + countX) { neighbour[3] = nodeGraph[id + countX]; } if (nodeGraph.Length > id + countX + 1) { neighbour[4] = nodeGraph[id + countX + 1]; } } } else if (id >= countX * countZ - countX) { //print("last row"); neighbour[0] = nodeGraph[id - 1]; if (id != countX * countZ - 1) { neighbour[1] = nodeGraph[id + 1]; } if (id != countX * (countZ - 1)) { neighbour[2] = nodeGraph[id - countX - 1]; } neighbour[3] = nodeGraph[id - countX]; neighbour[4] = nodeGraph[id - countX + 1]; } //scan through all the node in the grid foreach (NodeTD node in neighbour) { //if this the node is not currentNode if (node != null && node.IsWalkable()) { //if this node is within neighbour node range neighbourDistance = GetHorizontalDistance(currentNode.pos, node.pos); if (neighbourDistance < neighbourRange) { //if nothing's in the way between these two if (!Physics.Linecast(currentNode.pos, node.pos, ~mask)) { //if the slop is not too steep //if(Mathf.Abs(GetSlope(currentNode.pos, node.pos))<=maxSlope){ //add to list //if(!node.walkable) Debug.Log("error"); neighbourNodeList.Add(node); neighbourCostList.Add(neighbourDistance); //}//else print("too steep"); } //else print("something's in the way"); } //else print("out of range "+neighbourDistance); } //else print("unwalkable"); } //set the list as the node neighbours array currentNode.SetNeighbour(neighbourNodeList, neighbourCostList); //if(neighbourNodeList.Count==0) //Debug.Log("no heighbour. node number "+counter+" "+neighbourNodeList.Count); } counter += 1; } return(nodeGraph); }
public void UnbuildTower(NodeTD node){ node.walkable=true; for(int i=0; i<subPathList.Count; i++){ subPathList[i].SearchNewPath(nodeGraph); } }
public static NodeTD[] GenerateNode(PlatformTD platform, float heightOffset) { if (instance == null) { Init(); } Transform platformT = platform.thisT; float gridSize = BuildManager.GetGridSize(); float scaleX = platform.thisT.localScale.x; float scaleZ = platform.thisT.localScale.z; int countX = (int)(scaleX / gridSize); int countZ = (int)(scaleZ / gridSize); float x = -scaleX / 2 / scaleX; float z = -scaleZ / 2 / scaleZ; Vector3 point = platformT.TransformPoint(new Vector3(x, 0, z)); thisT.position = point; thisT.rotation = platformT.rotation; thisT.position = thisT.TransformPoint(new Vector3(gridSize / 2, heightOffset, gridSize / 2)); NodeTD[] nodeGraph = new NodeTD[countZ * countX]; int counter = 0; for (int i = 0; i < countZ; i++) { for (int j = 0; j < countX; j++) { Vector3 pos = thisT.position; pos.y = pos.y + 5000; LayerMask mask = 1 << TDTK.GetLayerTower(); RaycastHit hit1; if (Physics.Raycast(pos, Vector3.down, out hit1, Mathf.Infinity, ~mask)) { nodeGraph[counter] = new NodeTD(new Vector3(pos.x, hit1.point.y + heightOffset, pos.z), counter); } else { nodeGraph[counter] = new NodeTD(pos, counter); nodeGraph[counter].walkable = false; } counter += 1; thisT.position = thisT.TransformPoint(new Vector3(gridSize, 0, 0)); } thisT.position = thisT.TransformPoint(new Vector3(-(countX) * gridSize, 0, gridSize)); } thisT.position = Vector3.zero; thisT.rotation = Quaternion.identity; counter = 0; foreach (NodeTD cNode in nodeGraph) { if (cNode.walkable) { //check if there's anything within the point LayerMask mask = 1 << TDTK.GetLayerPlatform(); mask |= 1 << TDTK.GetLayerTower(); if (TDTK.GetLayerTerrain() >= 0) { mask |= 1 << TDTK.GetLayerTerrain(); } Collider[] cols = Physics.OverlapSphere(cNode.pos, gridSize * 0.45f, ~mask); if (cols.Length > 0) { cNode.walkable = false; counter += 1; } } } float neighbourDistance = 0; float neighbourRange; if (instance.connectDiagonalNeighbour) { neighbourRange = gridSize * 1.5f; } else { neighbourRange = gridSize * 1.1f; } counter = 0; //assign the neighouring node for each node in the grid foreach (NodeTD currentNode in nodeGraph) { //only if that node is walkable if (currentNode.walkable) { //create an empty array List <NodeTD> neighbourNodeList = new List <NodeTD>(); List <float> neighbourCostList = new List <float>(); NodeTD[] neighbour = new NodeTD[8]; int id = currentNode.ID; if (id > countX - 1 && id < countX * countZ - countX) { //print("middle rows"); if (id != countX) { neighbour[0] = nodeGraph[id - countX - 1]; } neighbour[1] = nodeGraph[id - countX]; neighbour[2] = nodeGraph[id - countX + 1]; neighbour[3] = nodeGraph[id - 1]; neighbour[4] = nodeGraph[id + 1]; neighbour[5] = nodeGraph[id + countX - 1]; neighbour[6] = nodeGraph[id + countX]; if (id != countX * countZ - countX - 1) { neighbour[7] = nodeGraph[id + countX + 1]; } } else if (id <= countX - 1) { //print("first row"); if (id != 0) { neighbour[0] = nodeGraph[id - 1]; } if (nodeGraph.Length > id + 1) { neighbour[1] = nodeGraph[id + 1]; } if (countZ > 0) { if (nodeGraph.Length > id + countX - 1) { neighbour[2] = nodeGraph[id + countX - 1]; } if (nodeGraph.Length > id + countX) { neighbour[3] = nodeGraph[id + countX]; } if (nodeGraph.Length > id + countX + 1) { neighbour[4] = nodeGraph[id + countX + 1]; } } } else if (id >= countX * countZ - countX) { //print("last row"); neighbour[0] = nodeGraph[id - 1]; if (id != countX * countZ - 1) { neighbour[1] = nodeGraph[id + 1]; } if (id != countX * (countZ - 1)) { neighbour[2] = nodeGraph[id - countX - 1]; } neighbour[3] = nodeGraph[id - countX]; neighbour[4] = nodeGraph[id - countX + 1]; } //scan through all the node in the grid foreach (NodeTD node in neighbour) { //if this the node is not currentNode if (node != null && node.walkable) { //if this node is within neighbour node range neighbourDistance = GetHorizontalDistance(currentNode.pos, node.pos); if (neighbourDistance < neighbourRange) { //if nothing's in the way between these two LayerMask mask = 1 << TDTK.GetLayerPlatform(); mask |= 1 << TDTK.GetLayerTower(); if (!Physics.Linecast(currentNode.pos, node.pos, ~mask)) { //if the slop is not too steep //if(Mathf.Abs(GetSlope(currentNode.pos, node.pos))<=maxSlope){ //add to list //if(!node.walkable) Debug.Log("error"); neighbourNodeList.Add(node); neighbourCostList.Add(neighbourDistance); //}//else print("too steep"); } //else print("something's in the way"); } //else print("out of range "+neighbourDistance); } //else print("unwalkable"); } //set the list as the node neighbours array currentNode.SetNeighbour(neighbourNodeList, neighbourCostList); //if(neighbourNodeList.Count==0) //Debug.Log("no heighbour. node number "+counter+" "+neighbourNodeList.Count); } counter += 1; } return(nodeGraph); }
public bool CheckForBlock(Vector3 pos){ float gridSize=BuildManager.GetGridSize(); NodeTD targetNode=PathFinder.GetNearestNode(pos, nodeGraph); for(int i=0; i<subPathList.Count; i++){ SubPath subPath=subPathList[i]; if(Vector3.Distance(pos, subPath.startN.pos)<gridSize/2) return true; if(Vector3.Distance(pos, subPath.endN.pos)<gridSize/2) return true; if(subPath.IsNodeInPath(targetNode)){ subPath.altPath=PathFinder.ForceSearch(subPath.startN, subPath.endN, targetNode, nodeGraph); if(subPath.altPath.Count==0) return true; } } nextBuildNode=targetNode; return false; }
public void SingleNodePlatform() { nodeGraph = new NodeTD[1]; nodeGraph[0] = new NodeTD(GetPos(), 0); }
public void SetPlatform(PlatformTD platform, NodeTD node) { occupiedPlatform=platform; occupiedNode=node; }
public SearchQueue(NodeTD n1, NodeTD n2, NodeTD[] g, SetPathCallbackTD func) { startNode=n1; endNode=n2; graph=g; callBackFunc=func; }
public static NodeTD GetNearestNode(Vector3 point, NodeTD[] graph) { return GetNearestNode(point, graph, 1); }
public static SelectInfo GetSelectInfo(Vector3 pointer, int ID = -1, float towerSize = 1) { InitMask(); Ray ray = CameraControl.GetMainCam().ScreenPointToRay(pointer); RaycastHit hit; //for free from drag and drop mode if (UseFreeFormMode() && instance.dndTower != null) { if (Physics.Raycast(ray, out hit, Mathf.Infinity, maskTerrain)) { Collider[] obstacles = Physics.OverlapSphere(hit.point, towerSize, ~maskTerrain); if (obstacles.Length == 1 && obstacles[0].gameObject == instance.dndTower.gameObject) { obstacles = new Collider[0]; } if (obstacles.Length == 0) { return(new SelectInfo(hit.point)); } else { return(new SelectInfo("Invalid build-point!", hit.point)); } } return(new SelectInfo("No valid build-point has been found")); } //try to detect a platform and determine the node on it bool flag = Physics.Raycast(ray, out hit, Mathf.Infinity, RaycastForTerrain() ? mask : maskPlatform); if (flag) { if (hit.collider.gameObject.layer == TDTK.GetLayerPlatform()) { BuildPlatform platform = hit.collider.gameObject.GetComponent <BuildPlatform>(); if (platform != null) { Vector3 pos = platform.GetTilePos(hit.point, GetGridSize()); NodeTD node = platform.GetNearestNode(pos); if (ID > 0) { if (lastSelectID == ID && sInfo.nodeID == node.ID) { return(sInfo); } else { lastSelectID = ID; } } return(new SelectInfo(platform, node.ID)); } } else if (RaycastForTerrain()) { return(new SelectInfo("No platform has been found", hit.point)); } } return(new SelectInfo("No platform has been found")); }
public void ProcessNeighbour(NodeTD node){ ProcessNeighbour(node.pos); }