Recast agent configuration (reduce pushing effect)

Hello !

I fail to configure Recast agent parameters.
I start from this playground.

1) How to stop agent faster ? :x:
Agents take too much time to stop, I call this the sliding effect. I even had cases where 4 agents would start endlessly circling around the target point. At first, I thought to use separationWeight, but it does not resolve the problem. I still experience small tremors at best and really bad positioning at worse.
UPDATE : I was using ICrowd interface, not RecastJSCrowd ! With the latest we have onReachTargetObservable and we can use that to immediately stop the agent, as show in this playground. Sadly this technique only works for one agent : when we select 10 units, only one unit will reach the target position, unless to increase the target radius (don’t even know if possible) but this would affect final positioning for sure.
UPDATE 2 : I think we can play with velocity to detect slow movement and use teleport to stop the agent, it brings new problems but it could do the job. I will update the PG later.

Also, when using Typescript, we cannot use RecastJSCrowd as it brings type incompatibility (on Vector3 for example), the workaround is to cast only when needed.

2) How to reduce agent pushing effect ? :x:
One agent can push other without problem, how to reduce this effect ?
(we cannot see that on the playground sorry because I didn’t updated it enough)
UPDATE : Question already posted but without solution

3) How to ensure same agent speed ? :heavy_check_mark:
The playground above shows that agents do not always move with the same speed while they have the same configuration. This effect is exacerbated when we increase collisionQueryRange. Getting some difference is logical, but sometimes it is not.
UPDATE: setting a huge value for acceleration can do the trick.

Last playground

I read some parts of the official documentation but found nothing.

1 Like

Hi @ylacaute

  1. I ended up using the same trick with huge acceleration value. Then, you can compensate the lack of smaller acceleration with an independant transform node that has it’s position being interpolated with agent position. It’s a fake acceleration but it was ok in some of my cases.

  2. I reduced that effect by making the reach target bigger so agents do not push already arrived ones to be on the exact same spot. It also depends on your use case. if the probability to have more than 1 agent at destination, when no need to worry.

  3. I’ve note really seen that effect before. I guess it’s related to other factor like the configuration with other agents around. if you have a PG that clearly reproduce the effect, I’d be curious to debug.

1 Like

Thank you

1) How to stop agent faster ?
Playing with acceleration and velocity is fine. But when you have 10 selected (and grouped) units and you order them to move, some will immediately stop because that have low velocity. I implemented a kind of “retry to move with a delay”, I will consider this solution as acceptable for now.

2) How to reduce agent pushing effect ?

by making the reach target bigger

How do you do that ?

3) How to ensure same agent speed ?

I’ve note really seen that effect before. I guess it’s related to other factor like the configuration with other agents around. if you have a PG that clearly reproduce the effect, I’d be curious to debug.

The previous playground in point 3 shows that. Just click on a border, than another border : you will notice that one agent is coming very slowly sometimes while the 3 others agents have already reach the destination.

  1. IIRC, you can try to teleport agents. their speed should become 0
  2. there is this Babylon.js docs
  3. can you try to get Babylon.js docs for slower agent and check if it’s different from the others

1) How to stop agent faster ?

Maybe you didn’t understand what I was explaining, currently I already check for low velocity to stop agent and use teleport. This technique works fine but bring new problems.

When manipulating a large amount of unit, let’s say 20, some units cannot move because of others (first units must move in order to the other follow), so they immediately stop because low velocity. We need to “remember” the move order : the unit, for example, wait 100ms and retry a move.

I just finished to implement system like that (not without headaches :sweat_smile:)

But all this has also a another consequence : after using teleport, an agent is not moving and stop acting as an obstacle (strange behavior from Recast by the way). As the result we have to add/remove obstacle each time the agent stop/start moving, like you suggested in this comment.

I got something almost working, but sadly it seems that the obstacle is not removed faster, as the result : when the agent restart moving he is abnormally translated a little bit before restart.

Each character have this method :

private setAsObstacle(value: boolean): void {
  if (value) {
    let position: Vector3 = this.crowd.getAgentPosition(this.navigationAgentIndex);
    this.navigationObstacle = this.navigationPlugin.addCylinderObstacle(
      position,
      this.getConfig().agentParams.radius,
      this.getConfig().agentParams.height);
    console.debug(`[agent ${this.navigationAgentIndex}] add obstacle at ${position}`);
  } else {
    if (this.navigationObstacle) {
      this.navigationPlugin.removeObstacle(this.navigationObstacle);
      console.debug(`[agent ${this.navigationAgentIndex}] remove obstacle}`);
    }
  }
 // this.crowd.update(this.scene.deltaTime);    // bonus test (ugly result)
}

Without using this method, it works perfectly. But when I to set an obstacle when the character stop (at character position with same radius), the character restart with a small unexpected translation. I have tried to remove the obstacle, wait 1 second, and start moving, but it changes nothing.

By curiosity I also tried to update crowd with update method but I think I did not understand something, the result is very strange. Also I use webworkers.

UPDATE: all this is coming “just” because agents keep moving all the time (video). I think we should be able to specify a kind of a precision or something in order to just stop.
You also spoke about a maximum number of obstacles, i found nothing in the documentation. Do you know the limit ? (I plan to get hundreds of units :smiling_face_with_tear:)

2) How to reduce agent pushing effect ?
My bad sorry.

Thank you

Check this PG:

see the difference with or without commented line 58

There is still an agent that is moving (sometimes), no idea why. but I think playing with read radius and this forced destination can be a good solution.

There is still an agent that is moving (sometimes), no idea why

That is the main problem, in your playground it does not always happen because you don’t have enough units. I updated your playground (exact same config, but bigger ground and 20 units) : https://playground.babylonjs.com/#X5XCVT#751

Stopping agent on onReachTargetObservable can help but I think it will never resolve the problem as it depend on the target radius, the number of selected units, and the distance between start and target position (this last one is true only if acceleration is low).

Here is another playground to illustrate this : https://playground.babylonjs.com/#X5XCVT#754
In this one we can see that a target radius too big works only if units come from a afar. When the target position is too close of selected group, they just don’t move.
Then, just increase the number of moving units and see the difference : https://playground.babylonjs.com/#X5XCVT#755
BUT this is working because first units stop when reaching the target position and they are pushed but others. This behavior will be a problem as soon as we will set a walking animation.

This behavior is even more clear when we set a huge acceleration : https://playground.babylonjs.com/#X5XCVT#756

I will search for a solution and come back later. My goals is really to manage units as in a RTS game.

Gotcha! navigation is not smart enough for what you want. IMHO, it need an extra process to determine the ‘ideal’ position at the destination.
I think you need formation or group navigation. treating each agent individualy like now is not enough.
Basically, you’ll have to compute a different destination for each agent.