Penalties are not working properly

Hello, I’m using recast graph in my game. My usecase is currently imagine if two characters are fighting amongst themselves other npc’s moves through them. I want them to take alternate way for that I’m trying to apply penalties to the node but it seems like even after applying penalty they are still using same path and moving though fighting npc’s. IS there any way to fix this issue

public void ApplyPenaltyToArea(Vector3 center, float radius, uint penalty)
{
    var graph = AstarPath.active.data.recastGraph;

    graph.GetNodes(node => {
        if (Vector3.Distance((Vector3)node.position, center) <= radius)
        {
            node.Penalty = penalty;
        }
    });
}

This may be an issue with the arguments themselves? What is the value of the penalty you’re setting? I tried this code just to make sure it’s not an issue with setting the nodes themselves and it worked fine. It’s simply your code but I took out the arguments and set it to random, so every node just gets a random value. I set my graph coloring to “Penalty” and worked fine. Every node changed color.

    public void RandomPenalty(){
        var graph = AstarPath.active.data.recastGraph;

        graph.GetNodes(node => {
            node.Penalty = (uint)Random.Range(0f, 5000f);
        });
    }

Can you share how your map looks after applying penalty? I tried applying high penalty from (1000-30000) but it didn’t work. Also maps color stayed same blue.

Be sure that you set your graph coloring to show the penalities. It does not by default. You can find it in the settings of your AstarPath component. This is what my graph does when I run that code.

i0721257738

Thanks. I tried again and penalties are applied to the graph but even then as you can see in the gif npc’s still walked through high penalty zone. What I’m trying to do in my game is that I’m applying penalty on recast graph when two character fight each other because right now if two characters are fighting on the point which falls on optimal path of other npc they kinda walk through them which looks weird https://drive.google.com/file/d/1_OPbrk3Kz4gc3R3xXvD1GxUZHBPKEpeY/view?usp=sharing

From the look of it, that looks like it’s because the cost of going through, even at it’s worst, is still much lower than it would be going around maybe? Try setting it to something absurd and seeing if you can get it to react from there- in the video you sent it looks like there’s a large amount of “walking around” that would need to be done.

I tried setting it upto 30000 but still got same result. Is there any other way I could achieve what I want other than penalties for recast graph?

There are, yeah. I’d say penalties would be the cleanest but you could probably take a look at :+1:

  • RVO/local avoidance (put the fighting NPCs onto a local avoidance layer that doesn’t collide with each other, but does with other NPCs?)
  • ITraversalProvider to maybe make nodes near fighters have a higher cost
  • You could even write a custom modifier for this
1 Like

Penalties on recast graphs are kinda tricky, because the nodes are so large. A penalty can only be applied to a whole node (triangle) at once, which usually doesn’t represent the shape you actually want.

When using penalties, grid graphs are usually more suitable.

If you want to use penalties with recast graphs, I would recommend that you use the 5.4.1 beta since it has significant improvements for penalties on recast graphs.
To get around the triangle shape issue, I would recommend you to use tags instead of raw penalties, and apply them using either Recast Graph Settings → Per Layer Rules, or by setting a custom tag by attaching a RecastMeshObj component to an object and configuring it to set a tag. This will shape the tag region to the object.

On your Seeker/FollowerEntity you’ll then want to increase the “Cost Per Distance” setting for that specific tag.

2 Likes

@aron_granberg @tealtxgr
Thanks for the response. Unfortunately, updating the Astar package is a last resort, as the game is in its final stage of development and I can’t use a beta branch. I ended up using the RVO approach, which seems to work well. However, the problem is: how do I make other agents take a route around the player? As you can see in the image, the player has an RVO collider that’s quite large. The AI just lingers around the boundary and doesn’t look for an alternate path.

I’ve quadtree implementation from that I could get nearby neighbors and their distance from the player, what I did when npc is within some threshold I add AlternativePath component to it take force it take different path. It somewhat works but still in many cases where it still linger around rvo boundary. Maybe there is some other way which I could take to solve this issue?

@aron_granberg @tealtxgr
To solve the issue, I duplicated the current recast graph on top of the existing one, renamed it, and added a NavMeshCut component to the player, which only affects the main recast graph. With this setup, NPCs are now avoiding other NPCs who are fighting(Fighting npc will transverse on 2nd recast graph). I’m caching both graphs, but I’m wondering if this will have any impact on performance. It will increase overall memory usage, but that’s something I’ll try to manage. However, are there any potential performance issues or anything else I might be overlooking?

1 Like

Great to hear that you managed to solve it!

Two graphs will double the memory usage, naturally. But it doesn’t have any significant effect on performance. GetNearest queries will be a bit slower unless they specify which graphs to search is the main thing I can think of.