canSearch/Destination vs StartPath

Hey folks,

Having a bit of trouble here and can’t find the answer.

My challenge is simple: Move actor from point A to B. A and B are both static points that do not change.

The problem: I set the “Destination” of the actor to point B. However I do not require the actor to “Search” for new paths all the way to point B every x interval (currently 2 seconds), and turning of canSearch breaks the “Destination” entirely.

Question 1: Is this intended?

The next problem: I tried to use StartPath with canSearch disabled, but it never seems to reach its destination “reachedDestination” even though it is over the point and the code works with “canSearch”.
I have tried increasing the “End Reached distance” to no effect.

Question 2: Is there something simpler I am missing for doing what I want? Has anyone else encountered this?

Cheers
Marco

Hi

  1. Disabling canSearch will make the agent no longer recalculate its own paths. You will have to call ai.SearchPath() manually to ensure path recalculations still happen.

I would advice against calling seeker.StartPath when you are using a movement script like AIPath. That is primarily for when you are using your own movement scripts. This might be a bit confusing in the docs/forums because previously calling seeker.StartPath has been possible, though not precisely recommended.
If you have a destination I would suggest setting ai.destination and calling ai.SearchPath which will make everything work nicely. If you want to use a custom path you can set it using ai.SetPath and that will make the AI calculate it in a way that it understands (i.e. things like ai.pathPending will work).

// Setting the destination is always required for ai.reachedDestination to work as
// that property measures the distance to the destination among other things.
ai.destination = whatever;
var path = ABPath.Construct(...); // Some custom path
// This will make the AI start to calculate this path, it will forward it to seeker.StartPath
// and also make sure that things like ai.pathPending work as intended.
ai.SetPath(path);

Generally though I would recommend to automatically recalculate the path every few seconds. You may not strictly need it, but it is very useful if for some reason the AI got off course or you update the graph by adding some new obstacle. Unless you have large number of agents the CPU cost should be pretty small.

Thanks so much for the reply,

I am using a large amount of agents yes and have optimized with Pro* as much as I can. I was thinking of hooking up the delegates to disable and enable can_search on path calculated and before (have not tested this).

The thing is I would’ve accepted the re-path calculations if I could set it to re-calculate every 10 seconds, although doing this also invites a perceived “lag event”. What I mean by that is if I set the path and the agent re-path rate is at 10 seconds, it will take the agent 10 seconds to actually start doing something from when destination was set. If it had immediately started the path and then started its recalculations it would’ve been much better, don’t you think?

Thanks again for your reply.

Hi

I think you will get that behavior if you do this:

// Recalculate very 10 seconds (you probably set this in the inspector though)
ai.repathRate = 10;

// Set the destination
ai.destination = whatever;
// Make sure AI recalculate the path immediately
// This will reset the timer, so the next path recalculation will happen 10 seconds from now
ai.SearchPath();

It’s not possible in general to just make the AI recalculate its path whenever the destination changes, because a very large number of games modify the destination every single frame (e.g. when following a moving target).

Thanks will give it a go!

Hi

Another user just discovered that there is a bug in the reachedDestination property. It would only work if the agent’s y coordinate was close to zero. The fix will be included in the next version, but in the meantime you can replace the definition of the reachedDestination property with this:

/** \copydoc Pathfinding::IAstarAI::reachedDestination */
public bool reachedDestination {
    get {
        if (!reachedEndOfPath) return false;
        if (remainingDistance + movementPlane.ToPlane(destination - interpolator.endPoint).magnitude > endReachedDistance) return false;

        // Don't do height checks in 2D mode
        if (orientation != OrientationMode.YAxisForward) {
            // Check if the destination is above the head of the character or far below the feet of it
            float yDifference;
            movementPlane.ToPlane(destination - position, out yDifference);
            var h = tr.localScale.y * height;
            if (yDifference > h || yDifference < -h*0.5) return false;
        }

        return true;
    }
}

Awesome thanks for all the support!