Pathfinding 2D RVO rotation before movement issue

Hi Aron,

I’ve modified your code in such a manner that units start moving only when they are a within a certain angle from their desired direction. I’m using a calculated grid targeted group movement for the end spots, that way the units won’t be fighting for the same spot.

I face a few problems :

  1. Sometimes, the units will not wait to turn within the requested angle before starting to move - so they move forced sideways.
  2. When they reach the desired spot, they’ll rotate on the spot quite a bit before calming down.
  3. Quite often, it feels like the RVO is not working. If I have two buildings close to one another, and space for just one unit, the units won’t give priority to others, so it won’t calculate properly.

If you need some show of code or visual examples, please let me know - I’ll be likely to upload these tomorrow ( eyes closing ). Best Wishes :slight_smile:

Hi

  1. It’s hard for me to answer that as it’s part of the code that you added.
  2. Which script did you base this on? The get started tutorial or one of the included movement scripts?
  3. I’m not quite sure what you mean. Do you think you could upload a screenshot or video?
    Generally RVO only considers very local adjustments. It will not be able to come up with a plan like “first back out of this corridor to let the other agent out, then move into the corridor”.
  1. The movement classes look this way :
    https://pastebin.com/Df971vZN
    https://pastebin.com/q9AY5snQ
  2. Can’t remember exactly, but you can see it in the code :slight_smile: . Either way, I’m using the RVO in 2d.
  3. You can see how a small piece of the game looks like and moves, here : https://ezgif.com/optimize/ezgif-5-19f14ce8b6.gif ( might take a while to load, it’s around 6 Mb ). You can see that every now and then units TWITCH on the spot, and rarely it happens that they start moving although they’re not directed properly.

Hi

The gif link seems to just redirect to the main website. I cannot see your gif.

It must’ve expired, I apologize for that. Here’s another version, https://cdn.discordapp.com/attachments/292485700639784961/398226292601782298/super_optimized.gif
if this doesn’t work for you either, please let me know and I’ll upload a new one on my hosting.

Hi

I think you should apply a bit of thresholding or smoothing before you rotate the unit. If the RVO says it should stand still, that point will be veeery close to the agent’s current position, and if you calculate the angle to that point it may end up as practically any value due to floating point errors.
I’d suggest rotating only when the movement delta is greater than some small threshold value. That should solve the issue.

Hi Aron, thanks for the reply. That solves the part when the units arrive to their last point - point 2) that I asked about. That was my solution as well, but I was wondering if you have a variable in your library specifically made for that :slight_smile: .
I still have the issue about number : 1) Sometimes, the units will not wait to turn within the requested angle before starting to move - so they move forced sideways.
I’m not sure if this was visible on the gif. Practically, as soon as I give a unit an order, it jumps for about 1-2 pixels, then starts rotating and moving accordingly. What I need to do is fix that jump, because it’s visually disturbing, specifically when I order about 10 units around.

Hi

You should move your speed limiting code before the agent tells the RVOController where to move, otherwise when a new path is calculated your code will tell the RVOController to move with full speed towards some point and only later in the frame change the maxSpeed variable, at which time it is too late.

Hi Aron, had to quadruple check everything before writing again.

So, I’ve done that, and it doesn’t work. I’ve tried a lot of things, and I think that it’s because of the RVO agent. Practically all I do is : set the maximum speed to 0.01, if the rotation isn’t aligned yet.
Detailed explanation : If the units are sitting in place and I give them a move order, they twitch, then start to rotate in order to align to the path.
If I let the units move onto the path for a while and then order them in a different direction, they twitch then start rotating.

Is there any chance that the RVO remembers their “should be” speed for a frame, then orders the movement ?

I made things work right with the help of a workaround that says : only allow movement if the speed is higher than 0.02 . I feel like my hands are dirty :stuck_out_tongue: .

Hi

RVO does calculations regularly, but not at the same time as you call SetTarget. So you may get the movement result from the previous frame for example. This is why you need to make that when you call SetTarget after the path has been updated, that the max speed is already limited. Otherwise it will think it can move at the maximum speed.
Do you think you could post your code again?

Hi Aron,
Certainly. I’ve made a zip file where you can see both the versions - the one that does the twitch, and the one with the workaround. I also added a version showcasing some of the game so you can grasp the issue first-hand.


You can select and move the units in a warcraft3 style.

Please feel free to look over it whenever you please, my workaround works great, so there’s no need really.
However, if you decide you have the time and manage to find the issue, please let me know, I’d greatly appreciate it. If you would like to look over any other classes ( behaviours, orders, switchers, etc.) , I’ll be happy to provide them. I use design patterns heavily so the code should be easy to grasp :slight_smile: .

Ah. I see what you are doing.

So what happens in your case is this:

  1. Unit is moving happily towards some point, or is standing still.
  2. The path is updated.
  3. The Update method of your script runs…
  4. Your script checks the velocity that the RVOController thinks the AI should move with (based on earlier movement commands) and updates the movement speed. It turns out that the agent was already rotated correctly so the movement speed is set to a high value.
  5. You script calculates in which direction it wants to move and sets the desired target point for the RVO controller along with the maximum speed it calculated previously. Now the thing is that the maximum speed was calculated with the assumption that the AI would move like it previously did, however when the new path was calculated the AI is suddenly moving in a different direction.
  6. The next frame the movement speed is updated again and now the movement speed is lowered due to the AI moving in a different direction.

The real issue is that there are cyclic dependencies. The RVO system wants to know how fast it should move, but for that you need to calculate the movement speed which depends on how the AI moves…

I think one safe approach to solve this is to simply limit the velocity that the RVO system returns to the current maximum velocity. The current maximum velocity and the maximum velocity that the RVO system used will usually be the same, however sometimes when there are large changes in how the AI moves they can be different.

Essentially change this code

var movementDelta = controller.CalculateMovementDelta(Time.deltaTime);
AdjustSpeedOnRotation(movementDelta);

to

var movementDelta = controller.CalculateMovementDelta(Time.deltaTime);
AdjustSpeedOnRotation(movementDelta);
movementDelta = Vector3.ClampMagnitude(movementDelta, maxSpeed);
1 Like

Btw. You might be interested in the function Mathf.DeltaAngle.

1 Like