Esempio n. 1
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);
    }
Esempio n. 2
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);
    }