Support Forum

Navmesh Add doesn't seem to work across multiple Recast Graphs?

I have been trying to use the Navmesh Add component to bridge a gap between my randomly generated dungeons doors, and I can’t seem to get it to work.

Unity_xTMPaAZptn

https://media2.giphy.com/media/FEjY8nVOFAze8ZfO0e/giphy.gif

As you can see, it can navigate to the end of one graph, but then stops because it can’t traverse to the other one using the Navmesh Add bridge that I made. I want this to be dynamic because some of these doors can be walls instead, it’s random.

I’ve tried using this component to traverse one raycast graph, and it seems to work (though its a bit finicky/glitchy tbh).

But trying to go across two diff recast graphs doesnt seem to work, even with the layermasks appropriately setup. (I noticed cut seems to work and make the right meshes, and add does seem to try to attach meshes together but idk it’s really hard to tell).

EDIT: It does seem to attach both meshes, but navigation still doesnt work
https://media2.giphy.com/media/tOdEkHH9QeaIKMc2DJ/giphy.gif?cid=790b7611c885a0e907060f2f69d297a4c10668426a34690b&rid=giphy.gif&ct=g

I don’t know what to do short of combining all the recast graphs for each room together into a single one once it loads. I’m already doing a lot of stuff like that just to get procedural terrain + recastgraphs to work, but this is getting me stuck. I’m not even sure links work across multiple recast graphs, I was having a lot of trouble with that as well.

my main question is: Is this feature broken? or am I doing something wrong?

Hi

It is not intended to be able to connect two separate navmeshes. You can connect two navmeshes using the NodeLink2 component, but I would recommend trying to use a single graph instead. A single graph is almost always preferable.

How do you go about combining multiple recast graphs into one? Is there functionality for this, if not, can you tell how you would go about doing something like this? I think I know how the matrices would work, but not sure about actually adding nodes properly to a recast graph.

Also I have a performance question, I’m wondering if having one large graph will impact performance because there are more nodes to traverse when pathfinding, rather than having it secluded to a bunch of smaller recast graphs?

It’s possible by saving/loading tiles. I followed this: Navmesh "Chunks" - #4 by joshcamas

The part that’s not covered is removing tiles. There’s a list of tiles that you can get when loading in a chunk – just use that to clear tiles.

However, I ran into a separate issue. There’s an internal tile limit, and our game is multiplayer. A* Pathfinding internally stores tiles/nodes in a 2D grid, so chunks can’t exist in separate grid spaces without generating all tiles in between. So I can’t use this :sob: but maybe you can.

Going to use this later when I implement chunk loading internally.

I see. I am a bit confused here, I see a lot of info about “replacing” tiles rather than specifically adding tiles to the recast graph.

Is it just a weird naming convention? It would be great to figure out if there’s an API for doing stuff like this. Also my grid spaces aren’t guaranteed to be evenly tiled, so idk if I can use this? I’m like half asleep so hard to reason about it, maybe it’ll be clearer in the morning. If you can provide more detailed explanation as to how to combine two recast graphs into one, I would appreciate it greatly!

These graphs are added procedurally. If we could have them as one graph we would but from what I understand its not possible.

How can we add two recast and point graphs together into one? (Each room has recast and point graphs as they all have verticality/jump points)

Hi

You can connect two recast graphs using multiple NodeLink2 components.

But generally, if your level is procedurally generated, would it not be possible to create a single recast graph to cover the whole level and scan that?

There’s some functionality for replacing existing tiles in a recast graph with a custom mesh. It’s mostly for internal use, but some users use it for various custom things.

This would be far too slow and inefficient. The voxel size is very high and it takes multiple minutes to even scan one room chunk.

We have already generated and cached, and then have it reloading the nodes into a recast graph at runtime, including the necessary matrix transformations to put graph at the right place… so procedurally generating these assets while not having it scan works great.

I will do this, but I’m wondering if you have a way of joining multiple recast graphs together?

This would be ideal, if I can load all these cached recast graphs we have, and then combine them into one on the data level.

The basic idea is this:

  1. Pre-generate all recast graphs per level chunk and save to cache (DONE)
  2. Once the level generates and places the chunks, load the saved recast graph cache (DONE)
  3. Combine all the recast graphs into a single recast graph by moving around the data from the loaded caches. (NOT DONE - HOW DO YOU DO THIS?)
  4. Now that these are all joined together, you can run navmesh add calls to join rooms together based on existence of a door or not, allowing AI to go through said door.

Obviously I can substitute the nodelink2 here… but I would like to avoid using links in this situation, as I think it would be better to have a single RecastGraph in my scene. (You seem to recommend this as well?)

All I’m asking is you point me to the right direction on how to connect all these graphs together into a single RecastGraph.

Is this internal method the right way to go about it? If so, can you provide a short code/pseudocode example of how you would take 2 RecastGraphs… say:

var RecastGraph1;
var RecastGraph2;

void Start()
{
    Join(RecastGraph1,RecastGraph2);
}

void Join(RecastGraph r1, RecastGraph r2)
{
  // How would you go about doing this?  Since the source is open, I'm just wondering if you had to do this with ur code, where would you start?
  // Do you create a new recast graph and then try to "ReplaceTiles" while providing tile data from r1 and r2?

}

A more detailed response would be very much appreciated @aron_granberg.
I’m planning on documenting how to pre-generate and load + combine recast graphs with the community afterwards, and even providing a route on integrating such a feature directly into your codebase afterwards.

I know a lot of people want to do similar things with this, as that is why Unity created NavMeshSurface to be used alongside prefabs. I’d like for this to have the same, and am more than willing to implement it functioning.

I did some experiments with this locally, and yes, it’s not a trivial problem.
I’ve written some code to make this easier and I’ll soon release it to the beta version.

Essentially, it consists of these building blocks:

  1. recastGraph.SerializeTiles, which takes a recast graph and serializes some tiles into a byte array.
  2. recastGraph.DeserializeTiles which loads tiles from a byte array and places the tiles at a specified tile offset (resizing the graph if necessary)

Together, they should make it possible to create a component that can hold this data in a prefab and allow it to replace the relevant part of the navmesh when the prefab is instantiated.
It will require your rooms to be aligned to recast tile boundaries, though. Will this work for you do you think?

Ok, so the functionality I’m trying to achieve needs these new functions you’ll be pushing out to beta and isn’t possible with the functions I presently have?

The first function I think I am already kind of using with saving out the RecastGraph to a file.
I think this may also save out the NodeLink3s? not 100% sure if that is even necessary to save out or if that matters but I use both the RecastGraph and NodeLinks for jumping within the game.

These sound essential to completing this implementation. Luckily the room chunks & bounds are grid based for the purposes of the procedural generation.

Please let me know as soon as this is available, have never accessed the beta branch associated with this asset.

Thanks a lot for the response, eagerly awaiting those functions.