Support Forum

Getting Error paths and Unhandled exception after a while

Hi, I’m getting lots of path.error in OnPathComplete but I simply handled the error by recalculating the path again. Also, there are times when the Path is Complete but the path.path is empty and the path.vectorPath is not.
But the real problem is that, sometimes, after trying to get the above errors, the pathfinding crashes with this:

ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. 
Pathfinding.Path.Trace (Pathfinding.PathNode from) (at Assets/Plugins/AstarPathfindingProject/Core/Path.cs:699)

Unhandled exception during pathfinding. Terminating.

Error : This part should never be reached.

The line that crashes is this one:

// Reverse
			int half = count/2;
			for (int i = 0; i < half; i++) {
				var tmp = path[i];
				path[i] = path[count-i-1];   <----- This line ------
				path[count - i - 1] = tmp;
			}

I’m currently in the version 4.2.3 so I don’t know if this is a thing that is already fixed in the newer versions.

Thanks.

Hi

Do you think you could post the exact code that you are using to recalculate the path?

Hi Aron,

This a summary of the code we use to Calculate the path.
We also include the script that handles the Pathfinding: UnitMovement.cs.txt (206.2 KB)

If I can provide any more information please tell me.

Thanks a lot.

    void StartPath(Vector3 v3CurrentPos, Vector3 v3posEnd, bool bWithBreakableObstacles = false)
    {
        if (seeker.pathCallback == null)
        {
            seeker.pathCallback = OnPathComplete;

            seeker.startEndModifier.exactStartPoint = StartEndModifier.Exactness.ClosestOnNode;
            seeker.startEndModifier.exactEndPoint = StartEndModifier.Exactness.ClosestOnNode;
        }

        if (!GameControl.control.testsettings.bTraverseBreakableObstacles)
            bWithBreakableObstacles = false;
        int iTraversableTagsPrev = seeker.traversableTags;

        int iTraverseObstacle = seeker.traversableTags | (1 << AstarKofiExtension.iObstacleBreakable) | (1 << AstarKofiExtension.iObstacleBreakableFantasma);

        if (bWithBreakableObstacles)
            seeker.traversableTags = iTraverseObstacle;

        XPath myXPath = XPath.Construct(v3CurrentPos, v3posEnd);
        myXPath.calculatePartial = true;

        PathEndingCondition pathEndingCondition = null;
        if (fScopeCurrent > 0.1f)
        {
            Vector3 v3Aux = v3posEnd;
            if (unitInfo.unitAI.myRival != null)
            {
                v3Aux = unitInfo.unitAI.myRival.unitAI.transformAI.position;
            }
            pathEndingCondition = new XPathEndingCondition(myXPath, v3Aux, fScopeCurrent - UnitMovement.FMOVETODIST);
        }
        else
        {
            pathEndingCondition = new ABPathEndingCondition(myXPath);
        }
        myXPath.endingCondition = pathEndingCondition;

        Path path = seeker.StartPath(myXPath);

        seeker.traversableTags = iTraversableTagsPrev;

        bCalculatingPath = true;
    }

    public class XPathEndingCondition : ABPathEndingCondition 
    {
        // Maximum world distance to the target node before terminating the path
        public float fMaxDistance = 10;
        public Vector3 v3Objective;

        // Reuse the constructor in the superclass
        public XPathEndingCondition (ABPath p, Vector3 v3Objective, float fMaxDistance) : base (p) 
        {
            this.fMaxDistance = fMaxDistance;
            this.v3Objective = v3Objective;
        }

        public override bool TargetFound (PathNode node) 
        {
            return base.TargetFound(node) || (((Vector3)node.node.position - v3Objective).sqrMagnitude <= fMaxDistance * fMaxDistance);
        }
    }

    void OnPathComplete(Path p)
    {
        // Si a medio StartPath decidimos parar, esto valdrá false y el personaje se quedará quieto
        if (bCalculatingPath)
        {
            bCalculatingPath = false;

            p.Claim(this);

            PathCompleteState pathCompleteState = p.CompleteState;
            if (p.path.Count == 0 || ((p.error || pathCompleteState == PathCompleteState.Error || pathCompleteState == PathCompleteState.NotCalculated) && (unitInfo.unitAI.moveToClassCurrent == null || !unitInfo.unitAI.moveToClassCurrent.bSkipObstacleBody)))
            {
                // ... ERROR. We call recalculate path here after a few seconds.

                p.Release(this);
                return;
            }
            
            // ... We use the p.vectorPath for the unit movement.

            p.Release(this);
        }
    }