Jittering on lightweight rvo pathfinding

I am trying to run pathfinding using some code from the lightweight RVO example on top of basic recast graph pathfinding. It is not using any modifiers, and there isn’t really any problem with the path itself, but the agent is jittering quite a bit as you can see in the footage:

For the movement, I am using a modified seeker script which calculates the movements and passes the target to the RVO simulator:

var vectorPath = vectorPaths.ToNativeArray(Allocator.Temp);

                    if (vectorPath != null && vectorPath.Length != 0)
                    {
                        while ((math.lengthsq(To2DIn3D(translation.Value - vectorPath[pathfinder.wp].Value)) < agentData.moveNextDistance * agentData.moveNextDistance &&
                                                                pathfinder.wp != vectorPath.Length - 1) || pathfinder.wp == 0)
                        {
                            pathfinder.wp++;
                        }

                        // Current path segment goes from vectorPath[wp-1] to vectorPath[wp]
                        // We want to find the point on that segment that is 'moveNextDist' from our current position.
                        // This can be visualized as finding the intersection of a circle with radius 'moveNextDist'
                        // centered at our current position with that segment.
                        var p1 = vectorPath[pathfinder.wp - 1].Value;
                        var p2 = vectorPath[pathfinder.wp].Value;

                        // Calculate the intersection with the circle. This involves some math.
                        float3 t = VectorMath.LineCircleIntersectionFactor(To2DIn3D(translation.Value), To2DIn3D(p1), To2DIn3D(p2), agentData.moveNextDistance);

                        // Clamp to a point on the segment
                        t = math.clamp(t, 0, 1);
                        float3 waypoint = math.lerp(p1, p2, t);

                        // Calculate distance to the end of the path
                        pathfinder.remainingDistance = math.length(To2DIn3D(waypoint - translation.Value)) + math.length(To2DIn3D(waypoint - p2));
                        for (int i = pathfinder.wp; i < vectorPath.Length - 1; i++) pathfinder.remainingDistance +=
                                                        math.length(To2DIn3D(vectorPath[i + 1].Value - vectorPath[i].Value));

                        // Set the target to a point in the direction of the current waypoint at a distance
                        // equal to the remaining distance along the path. Since the rvo agent assumes that
                        // it should stop when it reaches the target point, this will produce good avoidance
                        // behavior near the end of the path. When not close to the end point it will act just
                        // as being commanded to move in a particular direction, not toward a particular point
                        float3 rvoTarget = math.normalize(waypoint - translation.Value) * pathfinder.remainingDistance + translation.Value;

                        // When within [slowdownDistance] units from the target, use a progressively lower speed
                        desiredSpeed = math.clamp(pathfinder.remainingDistance / agentData.slowdownDistance, 0, 1) * agentData.maxSpeed;

                        // Set target in rvo controller
                        data.SetTarget(agentData.rvoSimulationIndex, rvoTarget, desiredSpeed, agentData.maxSpeed);

When there are multiple units it does it less frequently, which leads me to assume it might be something to do with how the local avoidance.

I haven’t been able to figure out what is happening and thought I would check to see if this has possibly been an issue you have experienced. Any idea what might be causing this behavior?

Hi

What is the desired fps on the RVOSimulator component?
Also I think it would be helpful with some debugging lines, for example “this is the point I’m moving towards”.

I have been messing around with it quite a bit and with rvo turned off but the same movement applied it seems alright:

When setting the rvo target in the simulation by:

SimulatorBurst.AgentData data = ((RVOSimulator.active.GetSimulator()) as SimulatorBurst).simulationData;
data.SetTarget(agentData.rvoSimulationIndex, rvoTarget, desiredSpeed, agentData.maxSpeed);

and then apply movement in a system after the lightweightRVO jobs run (immediately after those jobs complete) that is when they move back and forth and jitter a lot. I am capturing the positional movement in the lightweightRVO job and saving it to a native array and applying it to the units in a system as mentioned. I capture in the JobMoveAgents from your script with

agentPositions[agentIndex] = pos + deltaPosition;
entityTranslations[agentIndex] = deltaPosition;

and applying the entityTranslations as an +=XZ offset in the system that modifies the entity translation.
I have the desired fps at 10, but have tried 1 and 60 and seem to get the same result just delayed with lower numbers.

I feel like it is updating the position with the deltaPosition calculated by RVO and then the next frame moving back to the previous position. but still trying to figure it out. Any ideas?

(It also might be worth mentioning that I am using a funnel modifier, converted to dots for burst compile, though it seems to be okay. Just when RVO is on it shakes back and forth)

Do you think you can use debug drawing to draw the (normalized) delta position, target position and other relevant variables?

Yes I can do that. Here is with RVO turned on

you can see some kind of get stuck in the same position

I’ll try to get the debugs in there

here is a look at the system with the debug lines.

the lines are:
green: current position to position + rvo delta position
red: current position to target position (put into the rvo SetTarget)
yellow: current position to the next wp in the path
white: line from last wp to next wp in path

the red line appears to be pointing towards the wp to wp line, so I assume that is correct. the green is the one that is used to move the entity which doesn’t seem correct. I am getting the green line as following which runs inside the rvo move-agent job:

for (int agentIndex = startIndex; agentIndex < endIndex; agentIndex++)
				{
					var pos = agentPositions[agentIndex];
					var deltaPosition = agentTargetPoints[agentIndex] - pos;
					float length = math.length(deltaPosition);
					// Clamp the movement delta to a maximum length
					var maxLength = agentSpeeds[agentIndex] * deltaTime;
					if (length > maxLength && length > 0) deltaPosition *= maxLength / length;

					**entityTranslations[agentIndex] = deltaPosition;**

I just realized that rvo calculations maybe adjusting the position with the assumption that the agent is looking at the target, which would explain the back and forth behavior. will test when I get the chance.

------------edit


so I figured out that it happens when the agent gets far enough away from the path line to where the waypoint is behind the agent. What I can’t figure out is why the green line (delta given by rvo) trends away from the path line.

In the picture above, the green line is the delta taken from rvo and added to the position. the redline is a line from the agent to the waypoint. this is running with only a single unit so I’m not sure why it is moving along side the line instead of directly ontop of it.

You can see here where the agent gets too far away from the path line and the waypoint line is more on the side instead of forward:

any help with why the green line (delta given by rvo) might be trending away from the path?

**EDIT
I was able to finally figure out the problem. Although initially the positional values were in sync, I had a piece of code that only applied the delta position if the unit was grounded, but my rvo jobs were applying those changes into the simulator, which caused desync. once I removed the positional updates from the job and applied them only when applied to the entity, it fixed it :slight_smile:
a lot of debugging for a simple/stupid mistake.