AI trying to make path through non-traversible tag

Hi there,

I’m having an issue with my AI where is trying to make a path through a non-traversible tag, if I stand on an edge of the tag. It will try and move through the tagged area instead of finding its way around. I know the tag is working correctly generally, because when I don’t stand in the tag, the path will loop around to the left.

Here’s a gif of what I mean:

ai-path-tag

The green is the tagged area, that works as expected provided I’m not standing inside it. If I stand inside it, the AI tries to move through it.

Any help is appreciated!

Hi

What are your Seeker -> Start End Modifier settings?

Hi Aron,

Apologies for the delay! My Start End Modifier settings are:

Start Point Snapping: Closest On Node Surface
End Point Snapping: Closest On Node Surface
Add Points: False

Hmmm… That is strange. It’s not what I would have expected. I’m not sure what could cause that with those settings…

Damn. So no ideas on how to fix it?

Hi @aron_granberg I’m finally back investigating this as I’m seeing it in a few different places.

One thought I had was maybe it’s occuring because there’s no other path to the location. Do you think that might explain it? I’d still expect it to just not be able to get there and return a fail or the closest point.

I’m using tags to lock doors and windows for the AI, and (I believe) they only seem to try and go through windows when there’s no other available path (all the doors are locked).

Are you using a custom movement script or one of the built-in ones?

I’m using the default AIPath script, referenced via my own script here:

public class NPCPath : MonoBehaviour {
    public AIPath AIPath;
    public NPCController NPCController;

    AgentBase Agent { get { return NPCController.Agent; } }

    Vector3 _desiredPosition;
    Quaternion _desiredRotation;

    public bool DisableCollision { get; set; }

    public bool IsStopped => AIPath.isStopped;
    public int StopFrame { get; private set; }

    CoroutineHandle _coroutine;

    void Awake() {
        _coroutine = Timing.RunCoroutine(WaitUntilEndOfFrame(), Segment.EndOfFrame);
    }

    void OnDisable() {
        Timing.KillCoroutines(_coroutine);
    }

    IEnumerator<float> WaitUntilEndOfFrame() {
        AIPath.rvoController = NPCController.AgentBehaviour.RVOController;

        yield break;
    }

    void Update() {
        ResetAIPath();
    }

    void FixedUpdate() {
        ResetAIPath();

        if (GameplayManager.IsPaused) { return; }

        UpdateMovement();
    }

    void ResetAIPath() {
        AIPath.canMove = AIPath.updatePosition = AIPath.updateRotation = false;
    }

    void UpdateMovement() {
        if (NPCController.State == NPCState.Dead) {
            Agent.MoveDelta(Vector2.zero);

            return;
        }

        AIPath.maxSpeed = Agent.GetNPCMoveSpeed(Agent.Health, NPCController.IsRunning, NPCController.IsCrouching);

        AIPath.MovementUpdate(Time.deltaTime, out _desiredPosition, out _desiredRotation);

        if (!Map.IsPlayerOnFloor(Agent.FloorIndex) || DisableCollision) {
            Agent.Position = _desiredPosition;
        } else {
            Agent.MoveDelta((Vector2)_desiredPosition - Agent.Position);
        }

        AIPath.FinalizeMovement(Agent.Position, Quaternion.identity);

        Agent.Position = AIPath.position; // Update Agent position in case any external forces were applied during AIPath.FinalizeMovement.
    }

    public int Stop() {
        AIPath.isStopped = true;

        StopFrame = GameplayTime.FrameCountFixed;

        return StopFrame;
    }

    public void Resume() {
        AIPath.isStopped = false;
    }

    public void Teleport(Vector2 position) {
        AIPath.Teleport(position, false);
    }
}

@aron_granberg OK, I think I’ve found a clue! It appears it might have to do with the Raycast Modifier. I have it set to Highest quality and Graph Raycasting. However if I disable it I can see the AI actually tries to take a path around the tagged area (which is slightly too tight, but that’s another matter I think). However the Raycast Modifier ends up moving the path through the window. Is there a way to make the Modifiers adhere to the non-traversible tags?

Here it is without the modifier:

Here it is with the modifier:


Separately, it thinks there is a valid path here between the non-traversible tag and the blocked nodes, but I can’t figure out why. It’s much tighter than the usual radius should all. Is it something to do with the tags not marking the area in the same way as a collision detection?

tight-path

I’m not 100% sure why the modifier would result in the very first image I posted in this thread. But it’s possible I suppose? Though there shouldn’t be a valid path to the player at all for it to then smooth.

Hi

The raycast modifier has indeed had a bug where it would treat non-traversable tags as traversable. It was fixed in the 4.3.20 beta.
You can download the beta here: https://www.arongranberg.com/astar/download

Hi @aron_granberg, thanks! Unfortunately it seems that I can only download the beta through the Unity package manager? My project is on Unity 2017.4 LTS. Additionally is there much risk in running a beta version of the system?

Hi

Yeah I’m afraid the beta requires Unity 2019.3 or later due to some dependencies it has.
The beta is quite stable. Usually more so than the non-beta version. However the grid graph has some features that are supported at the moment. Most notably the ‘erosion uses tags’ setting.

Uh oh. Upgrading Unity isn’t a possibility, as the game is very near completion, and it would likely be a nightmare. Does that mean I’m unable to get the modifier fix?

Hi

Here are the two diffs that are required for it to work:

https://pastebin.com/tBCVnLs5
https://pastebin.com/YzRzPFWm

Hi @aron_granberg,

Thanks for this, unfortunately I seem to be having issues patching it. I get the error:

error: corrupt patch at line 282

For tBCVnLs5, and a similar one also on the last line for YzRzPFWm. I tried adding a new line to the end of each. This fixes YzRzPFWm, however some changes are then rejected presumably because I haven’t run tBCVnLs5 first?

Edit:

So I realised I’m not on the latest stable version which might be causing an issue. I have now updated, but it seems that there’s a couple of C# 7.0 lines in RichPath.cs:

:161 -- if (part is RichFunnel funnel) {
:168 -- } else if (part is RichSpecial link) {

They’re fairly easily changed on my end, but the changelog doesn’t say anything about dropping support for 2017.4.

Unfortunately it also didn’t solve the aforementioned issue with the patch files, hehe.

Hi again @aron_granberg, sorry to ping you again, but I don’t suppose you have any ideas why the diffs aren’t working?

Hi

The current dev version may be sufficiently different from your version that it might be hard for git to patch it directly. You can try to patch it manually by editing the code. It’s not that many changes so it should hopefully be fairly quick.

Ah, yeah I wasn’t completely sure when C# 7 was introduced to Unity. I should probably update the download page with the new minimum version…

Thanks @aron_granberg, I made the changes manually and it seems to be working fine!

As a side note, the reason my AI were trying to move through a small space was because I forgot that the tag system isn’t aware of my game, hehe. So if I smashed a window, it would mark its area as clear, even if that overlapped another window that wasn’t clear. Silly me.