4
\$\begingroup\$

I am developing an RTS-like game, that have units that move and attack. I implemented path-finding and local-avoidance.

One problem is when multiple units being ordered to the exact same position, they can never reach the position due local-avoidance and collision.

Only this will make the units scratch each other, this will also cause the unit not able to STOP, as the unit might be still far from the target position. And whether stopped or not is important for battle (unit can only attack when stopped).

I studied how SC2 handles this, it appears that the units will stop after a few seconds of scratching.

PS, I have used group formation to avoid the situation, but it can not be avoided, when the group are ordered to goto some impossible position, and they would cluster at the edge of the valid navmesh.

\$\endgroup\$
4
\$\begingroup\$

AI War: Fleet Command handles this in two ways.

1) when multiple units are given a move command the game automatically computes unique stopping points for each unit, performing the local avoidance on each unit once knowing what space will be occupied at the destination and calculating dither and further spots away from the user's input by filling circles (that is, units get assigned a position on a circle starting at 0 degrees, when the circle fills up, the radius is increased, and the process repeats).

2) if a unit arrives at its destination and it is bigger than the units it landed on, it bumps the smaller units under it (this keeps things like golems from lumbering around, they bump everything, starships are smaller, but bigger than fleet ships, so they occupy a middle space, and fleet ships are the smallest; stationary units never get bumped). If its a small unit, it gets bumped instead. Bumped units pick a random new location it go to that's nearby (picks a random direction and flies until it finds open space). Usually settles down fairly quickly.

\$\endgroup\$
2
\$\begingroup\$

In a case like this, I'd measure the distance between the unit and the target position and if the unit did not get any closer to its target, then I'd also use the unit's last few positions to see if it has moved.

If the unit is not getting any closer to its target and it's not moving an amount you deem good enough, then it's time for this unit to stop.

The following code is just pseudo-code, and it assumes you're going to calculate the distances yourself, so it might not work out of the box, but it's basically what you need in a case like this (or at least some point to start your work from):

if((abs(previousDistanceToTarget - currentDistanceToTarget)) <
    predefinedGranularMovementAmount)
{
    /* 
    CalculateMovementAmount function calculates how much the unit's 
    position has changed in the last few seconds or even in the last 
    second depending on your personal preference
    */
    unitMovementDistance = CalculateMovementAmount();
    if(unitMovementDistance < predefinedGranularMovementAmount)
    {
        CancelUnitMovementOrder();
    }
}
\$\endgroup\$
1
\$\begingroup\$

increasing the stopping distance on the nav mesh agent allows you some space to line up around the selected goal position. That way if the goal location is crowded they will select the next closest distance within the range to stop.

you can also dynamically increase this if you have larger groups heading to one position. maybe setup a threshold so the stopping distance would be 2 unless more than 5 moving there then it can increase to 4 and so on.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.