News Forums RAIN General Discussion and Troubleshooting Disabling navMesh pathfinding in code

This topic contains 9 replies, has 4 voices, and was last updated by  Sigil 6 months ago.

Viewing 10 posts - 1 through 10 (of 10 total)
  • Author
    Posts
  • #38608

    ck
    Participant

    I’ve around 20-30 active NPCs that wander around following a waypoint network by going from waypoint to the next waypoint. The issue is that all the NPCs are still doing pathfinding (which is unnecessary since the paths are unobstructed anyway) and slowing down mobile performance to a crawl at times.

    What I’d like to do is to disable the Navigator’s pathfinding feature until the NPC senses and starts following the player. I’ve tried assigning non-existent graphTags and enabling Off Graph Movement, but the Navigator still reverts to the main NavMesh.
    Is it possible to selectively disable the pathfinding feature or if not what would be the best way to go about achieving this?

    • This topic was modified 1 year ago by  ck.
    #38621

    Sigil
    Keymaster

    Well the graph tags should get you what you want (in combination with Allow Off Graph Movement), but it looks like there is a bug (sorry). We aren’t properly clearing the graph when a graph tag is added/removed, so once your AI has picked up the Navigation Mesh he won’t let it go, even if the graph tags change.

    So just to be clear, this is what you would want to do to ignore all Navigation Meshes:

    // Technically this ignores all Navigation Meshes that don't have the "noGraph" tag
    AIRig tRig = gameObject.GetComponentInChildren<AIRig>();
    ((BasicNavigator)tRig.AI.Navigator).AddGraphTag("noGraph");

    And when you want to see all the Navigation Meshes again:

    AIRig tRig = gameObject.GetComponentInChildren<AIRig>();
    ((BasicNavigator)tRig.AI.Navigator).RemoveAllGraphTags();

    Well that won’t work right now… it will be fixed in the next version, but until then you can add this to make it work:

    // After adding or removing a graph tag, clear our current graph
    ((BasicNavigator)tRig.AI.Navigator).CurrentGraph = null;

    Sorry about that, thanks for reporting the issue.

    #38629

    ck
    Participant

    Thanks Sigil, the code works great for clearing the graph, unfortunately it doesn’t solve the performance issue since IsPointOnGraph() keeps getting called multiple times every frame. I have 13 active AIRigs in the scene but I’m seeing over 70 IsPointOnGraph calls from MechanimMotor.IsAt() and another 70+ from BasicNavigator.GetNextPathWaypoint(). However when I manually disable the NavMesh rig in my scene all those calls disappear.

    Is it possible to somehow have the AIRigs act as if there were no navmeshes in the scene whatsoever or disable IsPointOnGraph()?
    Here are some Profiler screenshots just in case you need some more data. The first one’s with an active Navmesh in the scene and “noGraph” tags set and the second one is with the NavMesh Rig completely disabled.
    NavMesh Active
    NavMesh Disabled

    • This reply was modified 1 year ago by  ck.
    #38632

    Sigil
    Keymaster

    Alright, I see where the issue is. So, unfortunately, with our current setup there is no way to simply deny an AI access to Navigation Meshes in the area outside of the graph tags. The good news is that I believe there are a couple really simple optimizations to make it much faster so that it won’t matter anymore.

    Send me an email (sigil@rivaltheory.com) and mention this post, and I will get you a development build of RAIN. I’ll need some time tomorrow to actually get it done, but I’ll send you a build after that and we can figure out if it fixes the issues for you.

    #39973

    xDavidLeon
    Participant

    Hey Sigil, sorry for reopening an old thread but we’ve been trying to optimize our game ‘Twin Souls‘ for a few months now and the bottleneck seems to be RAIN.

    In levels with a low quantity of enemies (around 10) the AI eats around 20% of the CPU, but other levels may contain up to 100 enemies. Of course, there’s some basic optimizations like disabling enemy GameObjects if they are really far away etc, but in any case we can see RAIN eating up to 70% of the CPU just trying to manage the AIs.

    The culprit looks like it’s BasicNavigator.IsAt() and MecanimMotor.IsAt(), which I think they contain calls to GetNextPathWaypoint() and IsPointOnGraph()… so that’s why I’m asking for help in this thread.

    Here’s a screenshot of the profiler, tell me if you need more info:

    Profiler

    So, is there any way to reduce the GC allocation or ‘disable’ the AI completely when the player is not around?

    Cheers!

    #39976

    Sigil
    Keymaster

    We’ll have a lot of optimizations for GC in the next version of RAIN, but it may not help you completely here anyways. Or maybe it will… if we can’t solve your problems here we’ll look into getting you a development copy of RAIN as well to see if it helps.

    So if you have a large number of patrolling AI using waypoints I would remove those AI from the navigation meshes using their graph tags. When they become alarmed or need to navigate, I’d put them back on the Navigation Meshes until they finish their task and go back to patrolling. This is assuming there aren’t a lot of static obstacles they have to get around while patrolling (although that can be alleviated by adding more waypoints, but that’s kinda annoying).

    Maybe there is a possible optimization here, where we automatically cache the paths along the waypoint routes… I’ll have to think on that though, a little more complicated.

    As a test, you could simply disable the Navigation Meshes altogether, and see how everything behaves. If that does a good job of reducing your calculations, then adding in the LOD I describe above would definitely help. If it doesn’t help at all then something else is going on and we’ll have to figure it out. I believe the change I describe in this thread is in the current version of RAIN, so disabling the Navigation Meshes should see some change.

    // In case you need it, here are the calls you can make.  As long as "Disabled" isn't in the
    // graph tags of any of the navigation meshes it should pop them off their meshes when you add it
    AIRig tRig = GetComponentInChildren<AIRig>();
    ((BasicNavigator)tRig.AI.Navigator).AddGraphTag("Disabled");
    ((BasicNavigator)tRig.AI.Navigator).RemoveGraphTag("Disabled");
    #39981

    xDavidLeon
    Participant

    Hey Sigil,

    Thanks a lot for the quick reply. I’ll try placing those calls and see what happens, although a big % of playtime takes place with enemies chasing you, investigating positions and looking for you, so I don’t think disabling temporarily the graph will fix all my issues. Regardless, your improvements on GC optimizations for Rain’s next version are super good news. Do you have an ETA for the next version? We can stay like this for a while, but our next deliverable milestone is on March.

    Cheers!

    #39994

    Sigil
    Keymaster

    In all likelihood it will be released pretty soon, well before March. Even if something happens and we don’t release it in time, you can contact us ahead of that and we can get you an early version.

    #40020

    RealGame
    Participant

    I pulled my hair out and figured out after turning on debug-paths that it is indeed calculating a path to each point in the waypoint route, no matter what. I thought it was because I used the wrong rig - Waypoint Network vs Waypoint Route. But the documentation interchanges these terms frequently, and even in the Waypoint path node itself it asks for a ‘waypoint network’ instead of a Waypoint Route.

    I just don’t see any navmesh based algorithms, no matter how optimized, can move 50+ AI’s on patrol routes without taking up at least 5ms.. even if all the paths are calculated lightning fast. And 5ms is going to start to hit your frame rate a little. Unless you re-invented A*, or radically optimized it for C# [no GC, all system classes, etc as you said]

    Currently each AI is taking 0.11ms minimum on the profiler. This caps AI in game, practically speaking, at around 50. If simple point to point movement is restored, and the navmesh is only accessed when going off-path, you could have 500.

    Caching the pre-calculated paths would be neat, and definitely fast. But I could see how it would become superfluous. I’d like to have a way to export the waypoints in the networks.. and more work go into that, because it’s a great layout tool and no other AI focusses on it because it’s not ‘high-tech’ - but it’s very useful.

    • This reply was modified 6 months ago by  RealGame.
    • This reply was modified 6 months ago by  RealGame.
    #40027

    Sigil
    Keymaster

    The general idea with the waypoints and how they work with the navigation meshes is that we want you to be able to drop waypoints where ever you like and the AI will deal with getting to them, despite any obstacles in its way. It seems overkill, but when the long term goal is to have dynamic obstacles, dynamic connections, doorways, other AI, etc, it gets a little clearer why we would need to query the graph between nodes.

    I think the correct solution here is to continue to optimize our pathing. We can do caching for frequently used paths, queuing for handling many AI at the same time, and threading to further address CPU usage.

    Short term optimization would be to use graph tags. Use a custom action to add a graph tag to your AI when it starts its optimized patrol route (could be anything, just as long as the navigation mesh doesn’t have it). When the AI breaks off the patrol, remove the graph tag again.

Viewing 10 posts - 1 through 10 (of 10 total)

You must be logged in to reply to this topic.