How to move Graph dynamically/tweak tough areas such as craters

Basically, our game world is made up of 9 terrain tiles at a given moment. Once you reach a certain point, 3 more tiles will be added to the side you are walking to, and 3 will be removed behind you. This means that our game world in a sense is always moving in some direction. I wanted to ask two things.
A. Is it possible to manually call SnapForceBoundsToScene from somewhere? (we are currently using javascript for the rest of our game, so hopefully this is possible from a cs script in the plugins folder)
B. If that is not possible, can we manually update the center of the graph in some way?

If both are not possible, any suggestions to get around this issue would be great.

We really would like to use recastgraph instead of something like a navmesh graph where our 3d team would have to go in and create the meshes themself.

In relation to that, my final question has two parts, and relates to a deep crater we want creatures to walk through.
C. I know it is possible to export the mesh under RecastGraph, but can I attach this navmesh created, to a prefab of 1 tile. Then proceed to use NavMeshGraph on that specific tile (using the file we exported)? I guess a better way of putting it is this. Can we add this mesh, GameObject with AstarPath attached, and any other variable I am forgetting to a prefab, and still have it work once it is loaded into the gameworld along side the other 8 tiles?
D. If the answer to C is true, then is it possible to have a general recastgraph covering all 9 tiles) PLUS the graph we attached to the 1 terrain tile where there is a small deep crater that needs special attention (something that the general recast over the 9 tiles can’t handle)

If you know of a better way to handle these few spots that need special attention or if you know of a way to tweak the recast variables to cover the crater as well please do :slight_smile:

Thank you for your time and effort you put into all of this,
Jon

I have learned a bit more since I made this post. For starters, I created the same kind of crater in a test environment, and the ai does just fine walking through it. For some reason though, our main world when scanned, only gets a few places on the ground mapped. The majority of the mesh gets placed randomly into treetops as well as rocks only. For some reason it just doesn’t see the ground. I even set all the trees/rocks to the obstacles layer, and it doesn’t even change the results.
Picture: i.imgur.com/gUpAYSR.jpg

This makes no sense because I can go into a test world with 1 terrain tile, and add obstacles to anything, and the scan will see it and adjust appropriately.

However, this goes into a problem I hope is on unity’s end.
I tried adding a capsule to the prefab of a tree, and change its layer to obstacles. Placing this into my test world, the scan for some reason ignores this layer. I can see the capsule with its tree parent in the hiearchy, and I can see that its layer is set correctly. What I have to do instead, is manually add a capsule into the scene, and move it into position inside the tree. Only then does the scan actually detect the layer. Is there something I am missing or not understanding?

If this is a problem, then I don’t know if we can handle trees added with the terrain paintbrush (no gameobject to click on). If instantiated capsules at runtime on these trees is going to still be ignored by the scan, then I am at a loss what the problem is.

It should be as simple as adding this capsule to the prefab, and if you manually drag it into the scene (which in some cases it is) or if you paint it into the terrain, then it should see the capsule child with its layer obstacles, and boom, make sure not to put a path inside it.

At this point however, I am more concerned about the scan putting mesh into treetops…

Hoping to hear from someone soon,
Jon

Hi

Couldn’t see that much in the image, consider lightening the scene up or at least not use .jpg with that heavy compression.

I recommend you to try the latest version, or if you already have that. Try the beta. It has much better options for rasterizing colliders and even trees added to terrains using the brush.

Probably the reason it is generating mesh in the treetops is because you are using large capsule colliders and apparently they were flat enough to walk on at the top. If you are using the Beta. You can add the RecastMeshObj component to those objects (won’t work with brush-trees though I am afraid) and set .area to -1. See http://arongranberg.com/astar/docs_FeatureFreeze/class_recast_mesh_obj.php#a5008f5aaa9ef50b1510e309dce9205d7

Using Javascript can be enabled from A* Inspector -> Settings -> Editor -> Enable JS Support. This will move folders around to enable JS to call into the pathfinding code.

Recast graphs are very slow to recalculate. You usually don’t do that during runtime except during loading screens.
But if you want to do it anyway, here is the code:
(AstarPath.active.graphs[0] as RecastGraph).SnapForceBoundsToScene(); AstarPath.active.Scan();

ah thank you so much for telling me how to snap it in the code.

Didn’t realize the screenshot was so dark. I guess I was really just trying to illustrate our problem. However, rickard (boss) seems to think his box colliders and other stuff he has set up is screwing the graph up (like you said, there might be an invisible “walk area” somewhere up there). So in light of that, I will just be going through each tile and exporting a navmesh, and then putting it on the navmeshgraph on the script that is also attached to the tile.

basically I did get the capsules working on tree prefabs so that they were radius 1 and ai could walk through the branches. However, there are quite a few brush-trees in each of these tiles. I was hoping you knew why the scan doesn’t detect the obstacles layer on these painted trees (since they come from prefabs that have the obstacle layer enabled on them)… Otherwise I am going to have to manually add a capsule to all these trees…

Exporting a navmesh and then using a navmeshgraph on each terrain tile is more optimized compared to using recastgraph correct?

Thank you again for your help, I will get back with you if I encounter any other problems than what I have mentioned here.

Jon

Recast graphs have basically the same speed during runtime as navmesh graphs, they are represented very similarly. Recast graphs take some initial time to scan though.

Are your terrain tiles going to be linked together? If so, I would actually advice you to use a recast graph instead, linking graphs does not always give good results because the pathfinding scripts and especially the modifiers cannot make many assumptions about how they are linked.

Trees which are brush-painted are not represented as normal GameObjects in the scene, therefore they would not be found by the graph generations scripts. I have to explicitly query the terrain object for all trees.

Before I go any further, here is a video of how our terrain generates.

If you think we need to use recast graph, that brings us back to the start of our problem again. I did find it interesting that in a test environment with one of these tiles (120x120), if I hit scan during runtime, it puts meshes all over the place (treetops as well), but if i scan without it running, it works just fine.

Rickard said that if your script detects Triggerboxes then we are screwed, because he has many of them in the main world. With that being said, in that test environment there are absolutely no hidden colliders anywhere. There were meshes just floating up in the middle of nowhere.

Apparently there is either something I am missing with settings in your script, or we really can’t use recast graph during runtime.

Couple things to note. I realized after adding the AstarPath script to the prefab tile, that in the main world it would throw up errors about having multiple AstarPath’s in the same scene. So that means in order for our navgraph idea to work, we would have to have one AstarPath, that dynamically hits the “Add Navmesh graph” button with what meshes are needed. As you said however, things can get bad if these tiles are linking together.

I did decide to put 2 terrain tiles next to each other just to test what you said. I added two navmeshgraphs to each tile. Indeed, I had to manually add a connection between the two for the ai to move to the other side. That is nice and all, but A. how would we dynamically add these points for our mainworld to connect these tiles? B. How would we know where there is an open space to put it? C. It is going to look stupid if our pack of wolves all pile up behind each other to cross one of these points

I decided then to try a recastgraph on these two tiles next to each other (something I have not tried yet). It only scanned one tile, and no matter what we tried (making the box surround the area and doing recast, making two boxes by making two recastgraphs) it wouldn’t look at both tiles.

If you have any suggestions on how we could make this work, please do tell. I know you said there would be a performance hit if we scanned every time the terrain loads in new tiles, but at this point I really just want this to work.

Hi

First of all. Download the beta version. You seem to have run in to some issues with terrains which have been fixed in the beta.

Option 1

Your world seems to be made up of pre made tiles, i.e not procedurally generated.
If so, then there is actually a way to load tiles and place them next to each other during runtime. I have developed the technique when working on Folk Tale. A game in which the world is build up using a lot of small tiles, all with their individual navmeshes. I think it could work for your case as well. (note, this requires the beta version).

Basically, you need to create meshes for all the tiles. Those can be exported from the recast graph inspector. Possibly they will need to be cleaned up and centered around the origin in a modelling application (or by script).

In the beta there is the class TileHandler.

At start, you would create a TileHandler with an associated recast graph. Then you can register all the prefabs’ navmeshes on that class (see doc link above).
Assumes that the mesh has its pivot point at the center of the tile.
If it has not, you can supply a non-zero centerOffset to offset all vertices.

You would have your recast graph at the world origin, covering 9 by 9 tiles (note the tileSize field on the Recast Graph). I recommend that when loading new tiles, you either move everything so that the middle tile is again at world origin (or at least in the centre of the recast graph) or you do something fancy with matrices.

When loading new tiles, you call the TileHandler.LoadTile method with the TileType objects you got from the register method before.

Hopefully this can at least get you started moving in the right direction. Tell me when you run in to trouble (you will probably since you would be the first one except me actually using the API).

Option 2

Simply use a GridGraph.
Grid graphs are relatively fast to scan, not sure how fast for your world, I doubt you would get away without at least noticeable lag unfortunately, but at least it would work.

Also see http://arongranberg.com/vanillaforums/discussion/881/understanding-the-documentation-when-building-a-grid-graph-in-runtime#latest

thank you so much for all of your input. I am leaving on my yearly vacation tomorrow, and will be back sometime next week. As such, I don’t know how much time rickard will get to look at this, let alone if he will get in contact with you/post here. I definitely did see how laggy the game got (<10 frames probably?) when I used the grid graph, so I don’t see that as a viable option.

Again, thanks so much for your help.
Jon

Make sure you don’t have gizmos enabled (Show Graphs) when you test grid graphs. Drawing the whole graph using gizmos is veeery slow.

Hi, I have a very similar setup to that described by darthclide, and I am loading/clearing tiles of the environment depending on the player’s position.

I was very pleasantly surprised to find out in the Beta you have implemented pretty much what I needed (recast graph loaded tile by tile), but I have a question about making the local avoidance work with that system.

I am currently implementing RVO components in my scene/on my AI, and I noticed that the RVONavmesh script which is supposed to turn the navmesh into RVO obstacles, will do an initial check of the graph, and I could manually trigger the AddGraphObstacles method to force it to update but that doesn’t sound ideal.

Any suggestions on how I could get RVO obstacles working with dynamic tiles?
I am about to dwelve into your code for RVONavmesh to see if I can refactor it to work with tiles instead of the whole graph (if I can figure out how, I’m not an advanced coder), would that be what you advise?

Can you foresee anything else related to RVO breaking up if using tiles like that (my alternative being to implement steering behaviors on my own based on colliders/raycasts)? Or did I miss something and there is a way of making this work with the current Beta code?

Thanks in advance!

PS: It’s not THAT critical that I get that working, as pathfinding + basic local avoidance will do the trick, but I’d like to use as much of the asset as I can :slight_smile:

Actually, the code for RVONavmesh isn’t so bad, I think I can reuse bits of that and of the TileHandler to create functions that will only clear/add obstacles based on a tile. I’ll try that and post again if I run into unforeseen trouble. Thanks

Very happy with the product by the way, was definitely well worth the price.