ProceduralGraphMover with RecastGraph long distance teleport problem

I’m using origin shifting in our 2d game so both the ProceduralGraphMover and agents need to teleport long distances when it happens.

 tr.position = Vector2.zero; // Teleport target transform of GraphMover to origin
 procGraphMover.UpdateGraph(false);
 eventRelay.Raise_On_OriginShift(_shift); // Teleports agents

I also tried this:

recastGraph.forcedBoundsCenter -= tr.position;
recastGraph.Scan();

But both approaches don’t work. Agent teleports to outer bound of recast graph at worst, it stutters visibly at best. What’s the correct way to approach this problem?

So you have a (seemingly non-player) agent far off from Vector2.zero, then move them to zero, but when you do, they end up not positioned correctly? I’m assuming tr is specifically your PreceduralGraphMover in a standalone GameObject? Let me know if this is correct so I’m not giving you the run-around :sweat_smile:. Although, I might have to do more research on origin shifting- seems straightforward but I also don’t want to pretend I understand something that I might not :slight_smile:

That said, the first thing that comes to mind is if you’re using the Teleport method to move your agent? Or are you directly moving it’s position/a parent’s position or something else? I’m curious what’s going on in Raise_On_OriginShift()

Let me know what you think/find!

Apologies for the bad explanation. ProceduralGraphMover is targeting SimulationZone(which is like a reality bubble, stuff outside of it is disabled or lightly simulated etc). To prevent precision errors whole world shifts back to origin after a certain threshold is passed. When this origin shift happens ProceduralGraphMover rightfully assumes that it’s target (SimulationZone) changed it’s position completely so does a full scan to update the recast graph however there’s no need for that because everything moved together so the recast mesh should stay the same. This needless full update causes a fps drop. Yes I’m using Teleport with agents but their constrainInsideGraph messes up during the origin shift. Here’s the bad solution I came up with to these problems

This code is executed during origin shift and is relocating recast graph manually:

AstarPath.active.AddWorkItem(() => {
recastGraph.forcedBoundsCenter += shiftOffset;
recastGraph.RelocateNodes(recastGraph.CalculateTransform());
});

Now because I change the bounds center, ProceduralGraphMover.RecastGraphTileShift() thinks that there’s no change in delta and to prevent a full graph scan I modified NavmeshBase.RelocateNodes() and commented out both DirtyBounds(bounds):

public void RelocateNodes (GraphTransform newTransform) {
...
/* DirtyBounds(bounds); */
...
}

I also changed ProceduralGraphMover.Update to ProceduralGraphMover.ManualUpdate so I can control it myself to prevent it from updating during an origin shift. (shiftOffset == Vector3.zero) means no origin shift happening in this frame

if (shiftOffset == Vector3.zero) procGraphMover.ManualUpdate();

I believe this works because I’m not seeing the big fps drop during the origin shift anymore and no problems with recast graph but I’m not %100 sure. I “solved” agent teleportation problem by setting constrainInsideGraph to false during the origin shift and then setting it to true one frame later after the Teleport like this:

public void TeleportNPC(Vector2 pos)
{
     ...
     Agent.Teleport(pos);
     DelayedEnable().Forget();
}

private async UniTask DelayedEnable()
{
     await UniTask.NextFrame();
     Agent.constrainInsideGraph = true;
}

Now all of these hacks work (I guess) but it doesn’t feel right. I searched the forums and doc but couldn’t find anything about origin shifting with ProceduralGraphMover. Is there a better way to handle this? Am I successfully tricking ProceduralGraphMover into believing that it didn’t move during the origin shift at all?