예제 #1
0
    //~ static public void GetPathX(Vector3 startP, Vector3 endP, Node[] graph, SetPathCallback callBackFunc){
    //~ Node startN=GetNearestNode(startP, graph);
    //~ Node endN=GetNearestNode(endP, graph);

    //~ //GetPath(startNode, endNode, null, graph, callBackFunc, false, true);
    //~ if(!searching){
    //~ //commence search
    //~ Search(startN, endN, null, graph, callBackFunc, true);
    //~ }
    //~ else{
    //~ //if a serach is in progress, put current request into a list
    //~ SearchQueue q=new SearchQueue(startN, endN, null, graph, callBackFunc);
    //~ if(urgent) queue.Insert(0, q);
    //~ else queue.Add(q);
    //~ }
    //~ }

    static public void GetPath(Vector3 startP, Vector3 endP, NodeTD[] graph, SetPathCallbackTD callBackFunc)
    {
        NodeTD startNode = GetNearestNode(startP, graph);
        NodeTD endNode   = GetNearestNode(endP, graph);

        GetPath(startNode, endNode, null, graph, callBackFunc, false);
    }
예제 #2
0
    public void InitNode(NodeTD[] nodeGraph)
    {
        Vector3 prevPoint;

        if (prevNeighbouringWP.platform != null)
        {
            Debug.Log("dong");
            //place holder, platform to platform connection not supported yet
            prevPoint = prevNeighbouringWP.platform.thisT.position;
        }
        else
        {
            prevPoint = prevNeighbouringWP.pos;
        }
        startN = PathFinderTD.GetNearestNode(prevPoint, nodeGraph);

        Vector3 nextPoint;

        if (nextNeighbouringWP.platform != null)
        {
            Debug.Log("ding");
            //place holder, platform to platform connection not supported yet
            nextPoint = nextNeighbouringWP.platform.thisT.position;
        }
        else
        {
            nextPoint = nextNeighbouringWP.pos;
        }
        endN = PathFinderTD.GetNearestNode(nextPoint, nodeGraph);

        //Debug.DrawLine(endN.pos, endN.pos+new Vector3(0, 2, 0), Color.red, 5);
        //Debug.DrawLine(startN.pos, startN.pos+new Vector3(0, 2, 0), Color.blue, 5);
        //Debug.DrawLine(nextNeighbouringWP.pos, nextNeighbouringWP.pos+new Vector3(0, 2, 0), Color.green, 5);
    }
예제 #3
0
    public void Prebuild(Vector3 point, UnitTower tower)
    {
        if (nodeGraph == null || nodeGraph.Length == 0)
        {
            return;
        }

        NodeTD node = PathFinderTD.GetNearestNode(point, nodeGraph, 0);

        node.walkable = false;

        List <NodeTD> nodeList = PathFinderTD.GetNodeInFootprint(node, tower.GetFootprint());

        foreach (NodeTD n in nodeList)
        {
            n.walkable = false;
        }

        tower.SetPlatform(this, node);

        foreach (PathOnPlatform pathObj in pathObjects)
        {
            queue.Add(pathObj.thisWP);

            PathFinderTD.GetPath(pathObj.startN, pathObj.endN, nodeGraph, this.SetPath);
        }
    }
예제 #4
0
 public SearchQueue(NodeTD n1, NodeTD n2, NodeTD n3, NodeTD[] g, SetPathCallbackTD func)
 {
     startNode    = n1;
     endNode      = n2;
     blockNode    = n3;
     graph        = g;
     callBackFunc = func;
 }
예제 #5
0
    public void Build(Vector3 point, UnitTower tower)
    {
        //pathfinding related code, only call if this platform is walkable;
        if (walkable)
        {
            if (tower.type != _TowerType.Mine)
            {
                //if build on the node last check for block, use the cached node and path
                if (nextBuildNode != null && Vector3.Distance(nextBuildNode.pos, point) < BuildManager.GetGridSize() / 2)
                {
                    //Debug.Log("use cached path");
                    nextBuildNode.walkable = false;

                    List <NodeTD> nodeList = PathFinderTD.GetNodeInFootprint(nextBuildNode, tower.GetFootprint());
                    foreach (NodeTD node in nodeList)
                    {
                        node.walkable = false;
                    }

                    tower.SetPlatform(this, nextBuildNode);
                    foreach (PathOnPlatform pathObj in pathObjects)
                    {
                        int rand = pathObj.pathID;
                        while (rand == pathObj.pathID)
                        {
                            rand = Random.Range(-999999, 999999);
                        }
                        pathObj.SetPath(pathObj.altPath, rand);
                        //forceSearch doesnt smooth path so path smoothing is call
                        //smoothPath will only valid path smoothing is enable in PathFinder
                        pathObj.SmoothPath();
                    }
                }
                //if build on node that is unchecked, find the block node and initiate a new path search
                else
                {
                    //Debug.Log("unexpected build point, query for new path");
                    NodeTD node = PathFinderTD.GetNearestNode(point, nodeGraph);
                    node.walkable = false;
                    //~ Debug.Log(node.ID);

                    List <NodeTD> nodeList = PathFinderTD.GetNodeInFootprint(node, tower.GetFootprint());
                    foreach (NodeTD n in nodeList)
                    {
                        n.walkable = false;
                    }

                    tower.SetPlatform(this, node);
                    foreach (PathOnPlatform pathObj in pathObjects)
                    {
                        queue.Add(pathObj.thisWP);

                        PathFinderTD.GetPath(pathObj.startN, pathObj.endN, nodeGraph, this.SetPath);
                    }
                }
            }
        }
    }
예제 #6
0
    void BlockNode(Vector3 pos)
    {
        NodeTD node = GetNearestWalkableNode(pos);

        pos.y = node.pos.y;
        if (Vector3.Distance(pos, node.pos) < NodeGeneratorTD._gridSize / 2)
        {
            node.walkable = false;
        }
    }
예제 #7
0
    void UnblockNode(Vector3 pos)
    {
        NodeTD node = GetNearestUnwalkableNode(pos);

        if (node != null)
        {
            pos.y = node.pos.y;
            if (Vector3.Distance(pos, node.pos) < NodeGeneratorTD._gridSize / 2)
            {
                node.walkable = true;
            }
        }
    }
예제 #8
0
    IEnumerator CycleNode()
    {
        int counter = 0;

        while (true)
        {
            yield return(new WaitForSeconds(0.15f));

            currentNode = nodeGraph[counter];
            counter    += 1;
            if (counter == nodeGraph.Length)
            {
                counter = 0;
            }
        }
    }
예제 #9
0
    static public 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);
    }
예제 #10
0
    NodeTD GetNearestUnwalkableNode(Vector3 point)
    {
        float  dist           = Mathf.Infinity;
        float  currentNearest = Mathf.Infinity;
        NodeTD nearestNode    = null;

        foreach (NodeTD node in nodeGraph)
        {
            if (!node.walkable)
            {
                dist = Vector3.Distance(point, node.pos);
                if (dist < currentNearest)
                {
                    currentNearest = dist;
                    nearestNode    = node;
                }
            }
        }
        return(nearestNode);
    }
예제 #11
0
    NodeTD GetNearestWalkableNode(Vector3 point)
    {
        float  dist           = Mathf.Infinity;
        float  currentNearest = Mathf.Infinity;
        NodeTD nearestNode    = null;

        //float rangeTH=gridSize*1.5;
        foreach (NodeTD node in nodeGraph)
        {
            if (node.walkable)
            {
                dist = Vector3.Distance(point, node.pos);
                if (dist < currentNearest)
                {
                    currentNearest = dist;
                    nearestNode    = node;
                    //if(currentNearest<rangeTH) break;
                }
            }
        }

        return(nearestNode);
    }
예제 #12
0
    static public void GetPath(NodeTD startN, NodeTD endN, NodeTD blockN, NodeTD[] graph, SetPathCallbackTD callBackFunc, bool urgent)
    {
        CheckInit();

        if (!searching)
        {
            //commence search
            Search(startN, endN, blockN, graph, callBackFunc);
        }
        else
        {
            //if a serach is in progress, put current request into a list
            SearchQueue q = new SearchQueue(startN, endN, blockN, graph, callBackFunc);
            if (urgent)
            {
                queue.Insert(0, q);
            }
            else
            {
                queue.Add(q);
            }
        }
    }
예제 #13
0
    public void UnBuild(NodeTD node, int footprint)
    {
        footprint = 0;

        //Debug.Log("unbuild  "+node.ID);

        node.walkable = true;

        List <NodeTD> nodeList = PathFinderTD.GetNodeInFootprint(node, footprint);

        foreach (NodeTD n in nodeList)
        {
            n.walkable = true;
        }

        foreach (PathOnPlatform pathObj in pathObjects)
        {
            //~ Debug.Log("update path");

            queue.Add(pathObj.thisWP);
            PathFinderTD.GetPath(pathObj.startN, pathObj.endN, nodeGraph, this.SetPath);
        }
    }
예제 #14
0
 public void UnBuild(NodeTD node)
 {
     UnBuild(node, 0);
 }
예제 #15
0
    void GenerateNode()
    {
        //float gridSize=GameControl.gameControlCom.TDS.gridSize;
        agentHeight = Mathf.Max(agentHeight, gridSize);

        area.x = Mathf.Floor(area.x / gridSize) * gridSize;
        area.y = Mathf.Floor(area.y / gridSize) * gridSize;

        area.width  = Mathf.Floor(area.width / gridSize) * gridSize;
        area.height = Mathf.Floor(area.height / gridSize) * gridSize;

        nodeGraph = new NodeTD[(int)((area.width - area.x) / gridSize * (area.height - area.y) / gridSize)];

        float timeStart = Time.realtimeSinceStartup;

        int   counter      = 0;
        float heightOffset = agentHeight / 2;

        for (float j = area.y; j < area.height; j += gridSize)
        {
            for (float i = area.x; i < area.width; i += gridSize)
            {
                RaycastHit hit1;
                if (Physics.Raycast(new Vector3(i, 500, j), Vector3.down, out hit1))
                {
                    nodeGraph[counter] = new NodeTD(new Vector3(i, hit1.point.y + heightOffset, j), counter);
                }
                else
                {
                    nodeGraph[counter]          = new NodeTD(new Vector3(i, 0, j), counter);
                    nodeGraph[counter].walkable = false;
                }
                counter += 1;
            }
        }
        //Debug.Log(counter);

        float timeUsed = Time.realtimeSinceStartup - timeStart;

        //Debug.Log("generate "+counter+" nodes, used "+timeUsed+"seconds");

        counter = 0;
        RaycastHit hit2;

        foreach (NodeTD cNode in nodeGraph)
        {
            if (cNode.walkable)
            {
                if (Physics.SphereCast(cNode.pos + new Vector3(0, heightOffset + heightOffset * 0.1f, 0), gridSize * 0.45f, Vector3.down, out hit2, heightOffset))
                {
                    cNode.walkable = false;
                    counter       += 1;
                }
            }
        }
        //if(counter>0) Debug.Log(counter+" node is unwalkable");

        float neighbourDistance = 0;
        float neighbourRange;

        if (connectDiagonalNeighbour)
        {
            neighbourRange = gridSize * 1.5f;
        }
        else
        {
            neighbourRange = gridSize * 1.1f;
        }

        timeStart = Time.realtimeSinceStartup;

        int rowLength    = (int)Mathf.Floor((area.width - area.x) / gridSize);
        int columnLength = (int)Mathf.Floor((area.height - area.y) / gridSize);

        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 > rowLength - 1 && id < rowLength * columnLength - rowLength)
                {
                    //print("middle rows");
                    if (id != rowLength)
                    {
                        neighbour[0] = nodeGraph[id - rowLength - 1];
                    }
                    neighbour[1] = nodeGraph[id - rowLength];
                    neighbour[2] = nodeGraph[id - rowLength + 1];
                    neighbour[3] = nodeGraph[id - 1];
                    neighbour[4] = nodeGraph[id + 1];
                    neighbour[5] = nodeGraph[id + rowLength - 1];
                    neighbour[6] = nodeGraph[id + rowLength];
                    if (id != rowLength * columnLength - rowLength - 1)
                    {
                        neighbour[7] = nodeGraph[id + rowLength + 1];
                    }
                }
                else if (id <= rowLength - 1)
                {
                    //print("first row");
                    if (id != 0)
                    {
                        neighbour[0] = nodeGraph[id - 1];
                    }
                    neighbour[1] = nodeGraph[id + 1];
                    neighbour[2] = nodeGraph[id + rowLength - 1];
                    neighbour[3] = nodeGraph[id + rowLength];
                    neighbour[4] = nodeGraph[id + rowLength + 1];
                }
                else if (id >= rowLength * columnLength - rowLength)
                {
                    //print("last row");
                    neighbour[0] = nodeGraph[id - 1];
                    if (id != rowLength * columnLength - 1)
                    {
                        neighbour[1] = nodeGraph[id + 1];
                    }
                    neighbour[2] = nodeGraph[id - rowLength - 1];
                    neighbour[3] = nodeGraph[id - rowLength];
                    neighbour[4] = nodeGraph[id - rowLength + 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
                            if (!Physics.Linecast(currentNode.pos, node.pos))
                            {
                                //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);
                    }
                }

                //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);
            }

            //Debug.Log(currentN.pos+"  "+currentNode.neighbourNode.length);
            counter += 1;
        }

        //timeUsed=Time.realtimeSinceStartup-timeStart;
        //Debug.Log("connect neighbour for "+counter+" nodes, used "+timeUsed+"seconds");
    }
예제 #16
0
    static public NodeTD[] GenerateNode(PlatformTD platform, float heightOffset)
    {
        //check if node generator
        CheckInit();

        //Debug.Log("generating nav node for "+platform.thisT);

        float timeStart = Time.realtimeSinceStartup;

        Transform platformT = platform.thisT;

        float gridSize = BuildManager.GetGridSize();

        float scaleX = platform.thisT.localScale.x;
        float scaleZ = platform.thisT.localScale.z;

        int countX = (int)(10 * scaleX / gridSize);
        int countZ = (int)(10 * scaleZ / gridSize);
        //Debug.Log(countX+"   "+countZ);


        float x = -scaleX * 10 / 2 / scaleX;
        float z = -scaleZ * 10 / 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++)
            {
                nodeGraph[counter] = new NodeTD(thisT.position, counter);
                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;

        float timeUsed = Time.realtimeSinceStartup - timeStart;

        //Debug.Log("generate "+counter+" nodes, used "+timeUsed+"seconds");

        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;
                }
            }
        }
        //if(counter>0) Debug.Log(counter+" node is unwalkable");

        float neighbourDistance = 0;
        float neighbourRange;

        if (nodeGenerator.connectDiagonalNeighbour)
        {
            neighbourRange = gridSize * 1.5f;
        }
        else
        {
            neighbourRange = gridSize * 1.1f;
        }

        timeStart = Time.realtimeSinceStartup;

        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];
                    }
                    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);
            }

            //Debug.Log(currentN.pos+"  "+currentNode.neighbourNode.length);
            counter += 1;
        }

        //timeUsed=Time.realtimeSinceStartup-timeStart;
        //Debug.Log("connect neighbour for "+counter+" nodes, used "+timeUsed+"seconds");

        return(nodeGraph);
    }
예제 #17
0
 public void ProcessNeighbour(NodeTD node)
 {
     ProcessNeighbour(node.pos);
 }
예제 #18
0
    //if this platform is part of a path, this function set the previous and next transform
    //public void SetNeighbouringWP(PathSection prev, PathSection next){
    //	prevNeighbouringWP=prev;
    //	nextNeighbouringWP=next;
    //}



    //check if building on particular point of the platform will block all possible route
    //use brute force check to return a flag instantly. try find a more perfomance friendly solution
    public bool CheckForBlock(Vector3 pos, int footprint)
    {
        float gridSize = BuildManager.GetGridSize();
        bool  blocked  = false;

        nextBuildNode = PathFinderTD.GetNearestNode(pos, nodeGraph);
        //Debug.DrawLine(nextBuildNode.pos, nextBuildNode.pos+new Vector3(0, 2, 0), Color.red, 0.5f);

        foreach (PathOnPlatform pathObj in pathObjects)
        {
            //Debug.Log("check path for "+pathObj.path);

            //check if the start of end has been blocked
            if (Vector3.Distance(pos, pathObj.startN.pos) < gridSize / 2)
            {
                return(true);
            }
            if (Vector3.Distance(pos, pathObj.endN.pos) < gridSize / 2)
            {
                return(true);
            }

            //check if the node is in currentPath, if not, then the node is buildable
            //this is only applicable if pathSmoothing is off
            if (!PathFinderTD.IsPathSmoothingOn())
            {
                bool inCurrentPath = false;
                foreach (Vector3 pathPoint in pathObj.currentPath)
                {
                    float dist = Vector3.Distance(pos, pathPoint);
                    if (dist < gridSize / 2)
                    {
                        inCurrentPath = true;
                        break;
                    }
                }

                if (inCurrentPath)
                {
                    //the current node is in current path, check to see if there's other alternative path if this one's blocked
                    //while getting another path, cache it so it can be used later without redo the search
                    //use force instant search so the path is return immediately
                    pathObj.altPath = PathFinderTD.ForceSearch(pathObj.startN, pathObj.endN, nextBuildNode, nodeGraph, footprint);
                    if (pathObj.altPath.Count == 0)
                    {
                        blocked = true;
                    }
                }
                else
                {
                    pathObj.altPath = pathObj.currentPath;
                }
            }
            else
            {
                //the current node is in current path, check to see if there's other alternative path if this one's blocked
                //while getting another path, cache it so it can be used later without redo the search
                //use force instant search so the path is return immediately
                pathObj.altPath = PathFinderTD.ForceSearch(pathObj.startN, pathObj.endN, nextBuildNode, nodeGraph, footprint);

                if (pathObj.altPath.Count == 0)
                {
                    blocked = true;
                }

                if (blocked)
                {
                    break;
                }
            }
        }

        return(blocked);

        /*
         * float gridSize=BuildManager.GetGridSize();
         *
         * //check if the start of end has been blocked
         * if(Vector3.Distance(pos, startN.pos)<gridSize/2) return true;
         * if(Vector3.Distance(pos, endN.pos)<gridSize/2) return true;
         *
         * //check if the node is in currentPath, if not, then the node is buildable
         * //this is only applicable if pathSmoothing is off
         * if(!PathFinder.IsPathSmoothingOn()){
         *      bool InCurrentPath=false;
         *
         *      foreach(Vector3 pathPoint in currentPath){
         *              float dist=Vector3.Distance(pos, pathPoint);
         *              if(dist<gridSize/2){
         *                      InCurrentPath=true;
         *                      break;
         *              }
         *      }
         *
         *      if(!InCurrentPath) {
         *      //Debug.Log("not in current path ");
         *              return false;
         *      }
         * }
         *
         *
         * Debug.Log("calling pathfinder, check for block");
         *
         * //the current node is in current path, check to see if there's other alternative path if this one's blocked
         * //while getting another path, cache it so it can be used later without redo the search
         * nextBuildNode=PathFinder.GetNearestNode(pos, nodeGraph);
         * //use force instant search so the path is return immediately
         * altPath=PathFinder.ForceSearch(startN, endN, nextBuildNode, nodeGraph);
         *
         * if(altPath.Count>0) return false;
         */

        //return true;
    }
예제 #19
0
 static public void GetPath(NodeTD startN, NodeTD endN, NodeTD[] graph, SetPathCallbackTD callBackFunc)
 {
     GetPath(startN, endN, null, graph, callBackFunc, false);
 }
예제 #20
0
 static public void GetPath(NodeTD startN, NodeTD endN, NodeTD[] graph, SetPathCallbackTD callBackFunc, bool urgent)
 {
     GetPath(startN, endN, null, graph, callBackFunc, urgent);
 }
예제 #21
0
    //~ 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);
    }
예제 #22
0
    static public List <NodeTD> GetNodeInFootprint(NodeTD origin, int footprint)
    {
        if (footprint <= 0)
        {
            return(new List <NodeTD>());
        }

        bool connectDNeighbour = NodeGeneratorTD.ConnectDiagonalNeighbour();

        List <NodeTD> currentList = new List <NodeTD>();
        List <NodeTD> openList    = new List <NodeTD>();
        List <NodeTD> closeList   = new List <NodeTD>();

        if (connectDNeighbour)
        {
            closeList.Add(origin);
            foreach (NodeTD node in origin.neighbourNode)
            {
                currentList.Add(node);
            }

            for (int i = 0; i < footprint; i++)
            {
                openList    = currentList;
                currentList = new List <NodeTD>();
                foreach (NodeTD node in openList)
                {
                    foreach (NodeTD neighbour in node.neighbourNode)
                    {
                        if (!openList.Contains(neighbour) && !closeList.Contains(neighbour))
                        {
                            currentList.Add(neighbour);
                        }
                    }
                    closeList.Add(node);
                }
            }
        }
        else
        {
            closeList.Add(origin);
            foreach (NodeTD node in origin.neighbourNode)
            {
                currentList.Add(node);
            }

            //~ float range=1.5f*(footprint)*BuildManager.GetGridSize();
            float range = 1 * (footprint) * BuildManager.GetGridSize() + BuildManager.GetGridSize() * 0.25f;

            for (int i = 0; i < footprint * 2; i++)
            {
                openList    = currentList;
                currentList = new List <NodeTD>();
                foreach (NodeTD node in openList)
                {
                    foreach (NodeTD neighbour in node.neighbourNode)
                    {
                        //~ if(Vector3.Distance(origin.pos, neighbour.pos)<range){
                        if (Mathf.Abs(origin.pos.x - neighbour.pos.x) <= range && Mathf.Abs(origin.pos.z - neighbour.pos.z) <= range)
                        {
                            if (!openList.Contains(neighbour) && !closeList.Contains(neighbour))
                            {
                                currentList.Add(neighbour);
                            }
                        }
                    }
                    closeList.Add(node);
                }
            }
        }

        return(closeList);
    }
예제 #23
0
    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);
    }
예제 #24
0
 static private void Search(NodeTD startN, NodeTD endN, NodeTD blockN, NodeTD[] graph, SetPathCallbackTD callBackFunc)
 {
     pathFinder.StartCoroutine(pathFinder._Search(startN, endN, blockN, graph, callBackFunc));
 }