Find Path to Location Sync absolutely kills performance during dynamic navmesh updates.

Hello all,

I’m currently working on making AI automatically walk around and interact with objects in a procedurally generated and dynamic world (Already implementated a 200x200 grid using Cellular Automata, that gets model assignment before splitting up into chunks of 20x20 instances so performance doesn’t drop when creating/destroying an instance vs having it be one huge instance array) , and have been using Find Path to Location Sync in order to both get points of a path to see the AI’s current travel destination, as well as the very important validating that the AI can indeed reach a target object’s location pulled from an array.

All of that seems to work well until I create or destroy an object/wall tile that causes the navmesh to update, which causes the FPS to drop to insanely low levels until the navigation is done generating. I’ve pinpointed it to the Find Path to Location node, after cutting that check out and just simply having the AI move directly to the object (placing or destroying an object/wall during the standard AI move with out the Find Path to Location doesn’t cause a performance drop at all)

It’s been pretty frustrating as my game right now is completely reliant on whether or not I can get the Find Path to Location node to function for validating reachable objects and displaying the AI’s paths. I did try using the Is Navigation Being Rebuilt bool as a hackmethod to skip the check if true, but it seems even that doesn’t properly function in shutting off a Find Path to Location in time.

I tried as a manual way to control when the navigation mesh will regenerate using the Initial Building Locked option in Navigation System settings, but there seems to be absolutely no blueprint option to ReleaseInitialBuildingLock() or something similar in manually turning on or shutting off dynamic updates for the nav mesh.

Attached is the segment in question that causes major performance issues while the navigation mesh is being updated. Removing the FindPathToLocationSync and check eliminates performance issues although will completely break things as it’s the only real way I can find so far to validate manually first that an object is indeed reachable before ordering the AI to target and move to it. Frustratingly, a MoveToLocation works just fine by itself but seems to have no way of pulling its path points from it.

Any help/suggestions/input would be much appreciated on the matter! I’m about this close to scrapping the navmesh system and floodfill the grid area for validation. :frowning:

6d00022963a04da93b659cda355f1aa1a7c44ff6.jpeg

Are you using dynamic invokers or a fully nav meshed world?

Currently it’s one big navmesh bounds along the map without invokers. I did mess around with having the colonists be invokers for awhile but it was too problematic for the type of game I’m creating. E.g. the player is able to have the colonists build buildings and alter the landscape/objects throughout the 200x200 tile area, which means that I’d have to make the radius absurdly large anyways due to the very nature of the whole map being alterable (there’s a large chance the AI won’t be able to know it can reach an object due to the possibilities of players building giant defensive walls, or there being mountains that were generated). It’s in a vein very similar to dwarf fortress, Rimworld, Stonehearth, etc.

11ac8d9ffbee9f3564aa5e08863b256ffb2bfe8d.jpeg


I was able to get the performance to 120/60 fps and the navmesh to generate quickly (couple of seconds on start, no problems with performance during object placement at runtime after initial generation) after messing around with the cell tile threshold. Unfortunately the FindPathToLocationSync causes performance to die during navmesh regeneration. I might end up toying with the idea of manually flood filling the grid into zones as a different way to validate whether an object is reachable and implement my own pathing, though that would be a rather unfortunate large amount of work.

Well, couldn’t get FindPathToLocationSync to work well enough for 20 active AI while the navmesh is updating because of a tile being created or destroyed. Did however decide to implement flood fill in blueprints as an alternative way to find out whether an object is within a tile that is reachable and that seems like it might work perfectly in the end!
7bacdceed795bd0103f6dbe8d3e855f915e9538a.jpeg
Now just to make it so it’ll correctly merge/separate zones when a tile is created/destroyed instead of flood filling the whole map again, and I should be golden! Might still have to expand further and make my own path query system if I want to be able to draw the path of the AI without FindPathToLocationSync though, doh! Maybe breadth-first-search will be good enough o_O

Just as an update for anyone curious who wants to use FindPathToLocation Synchronously without your game losing a ton of FPS when navmesh is rebuilding. I took a break from my floodfill algorithm to see if there still was someway to make FindPathToLocation perform better, and low and behold I found the answer while testing!

Create the node Enable Recalculation on Invalidation and plug the resulting path from FindPathToLocation Synchronously into it, setting the enum on the node to “No.” Of course while this works great for initial query so far, I’m guessing by the name it won’t update that FindPath automatically if say your navmesh rebuilds and the path is now blocked. It’s not a problem in my case though as I’m literally using it just for the initial “Is it reachable when we try to find out if it is” and to draw the path visibly for the player to see.

The built in move-to commands seem to automatically update with great performance anyways, so if anything I can just recast a new path to see if the item is still reachable on creation of blocking objects.

I’m not entirely sure how the AI Moveto Enum property works, but I’m guessing by its enum outputs it will automatically change to Failed if it can no longer reach the target. Possibly having a check that runs once in awhile to see the status of that enum might work as an additional way to see if the moveto command will no longer meet its target. All hypothetical at this point anyways, but yay for one more problem being solved.

3 Likes

Thanks for sharing this one :slight_smile: Really saved me alot of time…

Thank you Deathstickthis help me a LOT, keep up the good work with your game

You absolute godsend