Make areas walkable/not walkable for an agent during runtime

I am using a grid graph with many units. I have both water and ground. Now I want some units (fishermen) to be able to traverse water when I set them to that profession.

The two ways I can find to do this seems to have some drawbacks:

  1. I simply use tags and set water tag to traversable/non-traversable. The problem here is that even when set as non-traversable units will walk on it if it is the only way to get to their destination, which obviously will look rly weird and will cause units to walk on water randomly.

  2. Create a second graph which only has water layer set as walkable, and give unit Seeker this graph when unit needs to traverse water. The problem here is using 2 grid graphs complicates a lot of other things, and from reading your comments it is not really recommended.

Am I missing a better way that will do what I want?

Hi

  1. No… I don’t think they should.

  2. Using 2 graphs is only a problem if your graph gets pretty big. Then you may get into memory issues because, well, you are storing twice the number of nodes. Or performance issues in particular when updating the graphs (pathfinding performance will not really be affected).

Hi,

I tested number 1 a lot and they definently walk across non-traversable nodes if its the only way out. Is that not intended? The only time they dont is if its completely unwalkable, i.e an obstacle.

Good to know that 2 is an option, I guess I just cant use AstarPath.active anymore, since there will be several.

@aron_granberg Can you confirm that option 1 is supposed to work and works for you? Since that would be a much better solution than 2.

Thanks!

@aron_granberg Hi Aron, if you want I can send u footage that shows units walking thru tags set as traversable = false when that is their only option to get to their destination.

Unlike unwalkable nodes where they actually get stuck as intended.

Hi

Option one definitely works for me.
If you test it, make sure you do not have any path modifiers which may affect the result, and that your Seeker -> Start End Modifier -> End Point settings is not set to Original.

Thanks I setup a new project just to make sure and seems you are right, now I just have to find out what Im doing that is breaking this behaviour :slight_smile:

Okay so I found the issue, now I dont know if its a bug or intended, but seems odd.

Basically the ersion of adjacent colliders take priority over untraversable nodes. In my mind it should be the other way around? Because atm if I place an obstacle with a collider next to an obstacle that is set to untraversable, part of that untraversable obstacle all of a sudden becomes walkable because of the erosion of the adjacent collider obstacle.(To be clear, I use both collider based obstacles, and tag based, tag based are only for obstacles that have different rules for different AI, for example water)

On top of that, when I place an collider obstacle during runtime and call the code below, several untraversable nodes are reset, even ones not adjacent to the erosion.

public void UpdateGridGraph(Bounds bounds)
    {
        var guo = new GraphUpdateObject(bounds);

        guo.updatePhysics = true;
        AstarPath.active.UpdateGraphs(guo);
    }

This is what the GraphUpdateScene obstacle looks like for my tag based obstacle:

bild

So basically two big problems for me:

  1. Erosion overwrites untraversable nodes
  2. UpdateGraphs(guo) when removing a collider obstacle resets several untraversable nodes that are not within the bounds of that obstacle.

Here are some images for clarity:

Red obstacles are untraversable, purple obstacle uses a collider, so is completely unwalkable:
bild

The above but without meshes for clarity, as you can see erosion takes priority:
bild

Here is a shot AFTER I set the collider obstacle as a trigger and call UpdateGraphs(guo), as you can see it does not look good, in my game this scenario is typical when destroying a building:
bild

Another scenario with erosion off:
bild

Here is a shot AFTER I set the collider obstacle as a trigger and call UpdateGraphs(guo), as you can see it still effects adjacent untraversable nodes, in my game this scenario is typical when destroying a building:

Hi

That looks odd. When running UpdateGraphs(guo) it should expands its update region to make sure that erosion is recalculated for all nodes that need it. In your case it looks like you have set guo.updateErosion = false?

Hey,

There is a screenshot of the inspector, updateErosion == true, for me that setting changes nothing.
the only code or components used are in the post above I’ve tried everything I can think of, can it be a version issue?

Also, is erosion supposed to overwrite untraversable nodes? Cant see any scenario where that would be the wanted behaviour.

Is there any information I can share to help you help me?

Erosion never overwrites unwalkable nodes, I’m not quite sure what you mean here.
Erosion is however also based on tags, so it will overwrite other tags as it’s not possible to store two tags in a single cell.

Right, which is why I was careful to say “untraversable” nodes, i.e tags set as untraversable. I would just assume that those would always take priority, but as you can see in my images they get overwritten by erosion.

On top of that, even without erosion u can see in my image that connected node tags are effected when I remove an adjacent obstacle, seems quite buggy. I could ofc be doing something wrong but rly not much going on here.

Either way I rly dont think this approach works, The screens above are from a completely empty project with just ur asset imported. The issue with erosion is making units walk through things they should not be able to walk through.

The grid graph has no idea which tags are traversable or not. If a tag is traversible or not is determined by the Seeker component. To a grid graph it’s just another number without any particular significance.

The ‘erosion uses distance’ setting does not work well if you also want to apply other tags to your nodes because you will inevitably end up with cases where you both want to say “this node is close to a wall” and “this node should have tag X”. They will end up with conflicts.
To solve this you’d have to store the distance information separately from your other tag information. It’s possible to do this, but it requires some smaller changes to the package code I’m afraid.

Yes that graph update does indeed look very buggy. I cannot replicate this locally. Which version of the package are you using? The beta has some rewritten code for this and that definitely shouldn’t be buggy.

That makes sense, I understand better then. Well I dont mind just skipping erosion completely tbh, I think the traverable/untraversable is more important. Unless you know some other way that is better, basically for things like water, where units should never be allowed to walk unless they are in state swimming.

So then the only problem is the last screenshot, where for some reason adjacent tags are effected by removing an obstacle.

I am using 4.3.41

Could you re-post those screenshots without erosion?

Well, if the two modes are completely separate with mostly separate units, then a separate graph is usually better.

bild

Here is a shot AFTER I set the collider obstacle as a trigger and call UpdateGraphs(guo), as you can see it still effects adjacent untraversable nodes, in my game this scenario is typical when destroying a building:
bild

Nah only have one unit, humans :slight_smile: So for me untraversable would be better if I can just get passed this “bug”, or whatever it is.

To be extra clear, this is the code I run after I set the collider as triggers:

public void UpdateGraph()
    {
        Bounds bounds = mCollider.bounds;
        var guo = new GraphUpdateObject(bounds);
        guo.updatePhysics = true;
        
        AstarPath.active.UpdateGraphs(guo);
    }

Ah. So when a region is recalculated with updatePhysics it will try to recalculate everything inside that region. This includes the tag. Since you have probably assigned your tag using a GraphUpdateScene component, that will be lost because the GraphUpdateScene component only applied the tag once and then its done.

I would suggest that you instead use some of the newer functionality in the beta which is designed to be more robust against cases like this. In the grid graph there’s a button called “Add Rule”. You can add a rule called “Per Layer Modifications” and make any object on the Water layer mark those nodes as having the water tag (for example).
This is much more robust because it will be checked whenever the graph is updated. Or to borrow a term from programming languages: it is declarative instead of imperative.

Ah! Sounds promising, Ill try that this week and let you know :slight_smile: Thanks a lot!

Just since Im curious, when you say “region”, what do you mean? Because its quite clear in the screenshot that the obstacle and tags dont overlap at all, so I would not say they are in the same “region”, maybe Im misunderstanding?

1 Like

When a part of the graph is updated (i.e. calling UpdateGraphs(bounds)), a region (an axis aligned rectangle) a bit larger than the bounding box you passed in needs to be updated. This is because of things like the erosion settings, collision diameter settings and a few other things. Essentially it needs to make sure to update all nodes that could potentially be affected by anything inside that bounding box.

1 Like