I’m trying to get a handle on penalty values in order to make it so that the agent would prefer the green path, instead of the orange path, in this screenshot. With a grid graph I’d have a node for every grid cell on the graph and could modify accordingly but I’m trying to first do this with a recast graph and these regions since our maps are massive and a grid graph just won’t perform.
The base penalty of the graph is 5000 and the green road in the screenshot has a negative penalty of -4500. I’ve also tried 50,000 vs -45,000 just as a scale comparison but see the same behavior (the agent follows the orange line, not the green line)
This penalty is applied via GraphUpdateScene component and a NavmeshCut where the corners of the road define that cut region. I am currently applying the penalty directly from the GraphUpdateScene component and not a tag. Though I am still applying a tag for the region (Walkway1 in the screenshot). I don’t want to set the tag penalty for every agent that would navigate, just for the region itself at the moment.
I’ve done it this way as my understanding is the navmesh cut will ensure there are some actual nodes inside that region. But maybe the path from point A to point B here is so direct it’s never even really considering that path.
It’s hard to know if my setup is wrong, the code is wrong, or just the penalty values.
The code that applies the cut & graph update is pretty simple and just calls the GraphUpdateScene.Apply() method at the end. I’m assuming since I see the penalties applied to the region properly when setting the graph to display debug penalties that I am at least generally getting the area right. Could it be something like there are no nodes inside the region? Or are my penalty values just not tuned right
After using GraphUpdateScene.Apply() are you scanning the graph anywhere? This can be as simple as manually hitting the AstarPath’s Scan button during runtime for testing, or calling it in code.
I am not re-scanning the graph, is that really needed?
However if you instantiate it later in the game, you can make it apply it’s setting directly, or wait until the next scan (if any). If the graph is rescanned, all GraphUpdateScene components which have the Apply On Scan variable toggled will apply their settings again to the graph since rescanning clears all previous changes.
You can also make it apply it’s changes using scripting. GetComponent<GraphUpdateScene>().Apply ();
My understanding from this was that more scanning wouldn’t be necessary–I am calling the Apply method on GraphUpdateScene after I set up the navmesh cut and copy its points into the GraphUpdateScene points array.
Either way, I did try scanning during runtime just for testing, agent still didn’t want to take the path.
EDIT: Wanted to add that I’m not sure the NavmeshCut & GraphUpdate are marking the region properly? The navmesh cut does seem to cut the navmesh properly but the update is only highlighting a subset of the triangles.
EDIT2: After re-reading some docs I swapped to use a RecastNavmeshModifier instead of GraphUpdateScene (and setting a collider to define the region). This still has the same result. But it does seem closer to what I should be doing based on the docs.
Edit3: Been doing more debugging, I’ve captured a video with showing the search space toggled on while the graph is set to debug the F value of the search.
The agent has a 10000 penalty for the normal ground and a 4000 for the tagged area–tagged area a bit hard to see in the video but it’s the rectangular region defined in the middle of the agent’s way points. Using the tag debug view for the graph you can see the region a bit better. I’ve made the tile voxel count super low to be pretty sure that I’ve got nodes actually in this region. This tag is set using recastnavmesh modifier and the penalties are applied on the FollowerEntity.
It looks like your graph is extremely tile based. If so, I would recommend using a grid graph for this. It will behave much more predictably when it comes to penalties and such. The recast/navmesh graphs use approximations for this, which are not always great.
To make things more robust, I would also recommend using the grid graph rule “Per Layer Modifications”. Using that, you can make ground gameObjects with specific layers get different tags or penalties. GraphUpdateScene works fine, but they especially if they start overlapping, things can get tricky.
Keep in mind that the default cost of moving 1 world unit is 1000.
For your road, it looks like the agent would have to move around 4 blocks to the side (and 4 blocks back) just to be able to skip around 8 blocks of high-penalty ground. Looks like that would not necessarily be better, often worse.
A grid graph is not viable for this setup as the grid would need to be about 2.5k cells squared to cover the playable space. Which as I understand it is well beyond the suggested limit–I don’t know if the DOTS implementation has affected the suggested 1k limit for the grid graph at all (though I seem to recall that limit was typically a memory concern?). I’m basically trying this first with a recast graph to see how well this approach does because I’ll have to get a lot more creative with the grid graph.
My fallback was probably to create a point graph manually based off the game state using the locations of roads and entrances to buildings on the map as the points. Then, use those points for pathfinding and a path in world space and feeding those path points into the navmesh the agent actually walks on.