NavmeshCut reduces FPS to 8

I have a cached graph using the Recast graph. When the scene starts, the code will take objects in the scene that are supposed to be dynamic and add the NavMeshCut component at runtime.

Issue 1:
After the scene starts, I am spammed with warnings “Skipping degenerate triangle”. The warnings stop after several minutes.

Issue 2: The scene runs at about 8 FPS, even after the warnings stop

As a test, I disabled the code that adds NavmeshCutUpdater, making no other changes. After doing so, my FPS increased to 37

Hi

Are you moving a lot of those cuts every frame?
From the profile it looks like 15 tiles are being updated every frame, which is quite a lot.

None should be moving. Is there a breakpoint I could set to find out what is triggering it?

Hi

NavmeshUpdates.cs => ForceUpdate method around these lines would probably work

for (var cut = allCuts; cut != null; cut = cut.next) {
	if (cut.obj.RequiresUpdate(cut)) {

The reason it was called every frame is that some falling objects were underground. I recommend some kind of warning to NavmeshCut in such a case where the y value is very low and it updates every frame.

Also, performance-wise this isn’t the best approach

if ((updateInterval >= 0 && Time.realtimeSinceStartup - lastUpdateTime > updateInterval) || anyInvalidHandlers) {
ForceUpdate();

My scene has like 10,000 objects, so NavmeshCut.RequiresUpdate is called that many times. In my own code I only update these kinds of objects on collision and while it is moving, then disable the check afterwards.

My proposed solution, is rather than iterating through every object

for (var cut = allCuts; cut != null; cut = cut.next)

You have NavmeshUpdates just store a unique HashSet of NavmeshClipper and it’s up to NavmeshClipper to call something similar to AstarPath.active.UpdateGraphs(…) to notify that this NavmeshClipper requires an update. That way I can turn off updates for objects I know are not moving, or underground, for example.

Possibly I can add a toggle on the navmesh cut to indicate that it will never move. Otherwise the issue is that there is no possible way in Unity to get an event whenever something moves, a script needs to check it every frame. It’s possible this can be optimized with the new DOTS architecture though, since this operation can probably be SIMDed quite well.