Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Sending multiple agents to the same destination (or very close ones)

Discussion in 'Scripting' started by Kondor0, Aug 7, 2012.

  1. Kondor0

    Kondor0

    Joined:
    Feb 20, 2010
    Posts:
    596
    Hi

    Let's say I have two or more navmesh agents and I order them to go the same destination or to very close destinations. What could be an intelligent way of avoiding that they start colliding with each other and jittering because they can't be all in the same point?

    I thought that if I order them to go the same point at the same time I could calculate the closest points to the original destination (one for every agent) so they don't collide much. The problem is if I order an agent to move very closely to another agent, they are not in the same spot but they are too close so the colliding starts. Should I just order them to stop if they collide with each other? (but that could cause a problem if they get too close trying to reach diferent destinations)... or maybe I should tell them to stop if the distance to the destination is smaller than the distance to the agent that is colliding with them, I don't know.

    Any ideas?
     
    SweatyChair likes this.
  2. timsk

    timsk

    Joined:
    May 27, 2011
    Posts:
    177
    You could ask the agents to move themselves to a random position within a sphere, but this only reduces the chances of collisions, it wouldn't totally prevent it.

    You could use the nav agents size to calculate where it should move. Take the position you want, then each time you send an agent there, you could move the position by the previous agents size.

    Another thing to note is that the navmesh system already has crowd avoidance. So your agents should try to avoid each other. The problem when sending them to the same spot is that they usually end up walking around in circles around the agent who was lucky enough to make it to the right position.

    Be interested to hear others opinions on how to do this.
     
  3. Stephan-B

    Stephan-B

    Unity Technologies

    Joined:
    Feb 23, 2011
    Posts:
    2,269
    Since two agents cannot coexist in the same space, you need to figure out how you want to handle that... Is it ok if they get close to that location? Do you want one of them to get to the location and then other to stop near? What happens when they get to that location? Do they just stand there or do they move to some new location?

    I have been playing with Navmesh Agents lately and most likely could offer some suggestions. It would be helpful to know what you expect the Agents to do :)

    Just in case you haven't played with this, if you set the Agent's speed to zero before they reach the destination, they will coast towards that destination until they come to a complete stop. Acceleration also controls how fast they slow down. So given the speed and acceleration, you can ensure the agent stops just shy of the destination. At that moment, you can then set a new destination for these Agents.

    Assuming you need one Agent to get to the Destination and the other to stop short, I would have the Agent that is closest to the Destination generate an Event telling the Other Agents to back off or slow down. Using the speed and acceleration, you could stop the other Agents short of the destination while that single one gets there.

    You could also have each remaining Agent pick a random spot within a short distance of the destination. Of course far enough from each other so they all fit :)

    I wouldn't wait until the last second to fire that Event. I would do it a far enough from the Destination to ensure Agents aren't already almost on top of each other. You would have to experiment with what might look better... perhaps once the remaining agents receive the Event, they could each get assigned a slower random speed to allow them to separate a bit from each other.

    Anyway those are just a few ideas ... hope it helps.
     
    Last edited: Aug 8, 2012
    SweatyChair likes this.
  4. Kondor0

    Kondor0

    Joined:
    Feb 20, 2010
    Posts:
    596
    Thank you for the ideas, I didn't thought of having communication between the agents, I think that could be a good way of ordering them to stop or recalculating a path to the nearest point to the original destination BEFORE they start colliding (not really a random spot but a spot between the starting point of the agent and the destination could be better).

    I'll experiment during this week.

    Thanks.
     
  5. Chayat

    Chayat

    Joined:
    Jul 29, 2013
    Posts:
    7
    Just found this thread after having a similar issue. Agents randomly visiting waypoints sometimes visit the same ones and sometimes arrive at the same time. Neither agent can get to the waypoint so they start to dance with each other around the waypoint. Every other agent following the random waypoints will eventually join this futile dance, none of them ever reaching their goal.
    Sad times.

    I changed my HeadToNextWaypoint() method to use a bool which if true would assign a new waypoint even if the agent had not reached the last point.

    Then this allows the patrolling agents a bit of slop. Even if a bunch arrive at the same time they can all trigger the next waypoint method.
    if (Vector3.Distance(target, transform.position) < 2f)
    {
    HeadToNextWaypoint(true);
    }
     
  6. vollukas

    vollukas

    Joined:
    Apr 6, 2019
    Posts:
    7
    What I did was to ResetPath() once the agent has reached the point. This way when I set multiple agents to the same position, once the agent reaches the point he stops and then gets pushed around by another agent that also wants to reach the same position. After a short time, everyone reached their point and everyone stands still in nice random cluster of NavmeshAgents.

    Code (CSharp):
    1. private Vector3 currentDestination;
    2.  
    3. private void Update()
    4. {
    5.     if(Vector3.Distance(transform.position, currentDestination) < 2f)
    6.     {
    7.         agent.ResetPath();
    8.     }
    9. }
    10.  
    11. public void SetDestination(Vector3 destination)
    12. {
    13.     currentDestination = destination;
    14.     agent.SetDestination(destination);
    15. }