I'm working with C# in Unity, and I'm making a top-down space shooter game in which there are many different AI-controlled ships flying around. The problem is that these ships often fly on top of one another in passing, and sometimes even will fly the same route on top of one another if given the same waypoint. I want to add a system to steer my AI ships away from each other as well as other obstacles so that instead of overlapping one another when flying the same path they will fly side-by-side, and will also try to avoid things that pass in front of them.
My current system essentially works like this: The AI looks at all of the current objectives, points of interests, etc, and decides where it wants to be on the map (a coordinate). The AI then sends an input direction to the ship, which then applies acceleration in that direction and changes the velocity. Therefore, any solution to alter my ship's pathing would need to alter this input direction somehow.
So my first idea was to check if there are any obstacles (ships, asteroids, structures, etc) within a radius of the ship, increasing this radius based on the ship's velocity (higher velocity = larger "view" radius):
Collider2D[] hits = Physics2D.OverlapCircleAll(transform.position, ship.velocity.magnitude);
If there is something nearby, calculate the direction to that collision, then calculate the opposite direction and scale it to the reciprocal, which also has the added effect of making the aversion stronger the shorter the distance to the collision is:
foreach (Collider2D hit in hits)
{
if (hit.gameObject == gameObject) continue; // exclude self from the search
Vector2 v = hit.ClosestPoint(transform.position) - (Vector2)transform.position;
v = (1 / v.magnitude) * -v.normalized;
I would perform this for every nearby obstacle and add all of these together to get the avoidance vector:
avoidanceVector += v;
continue;
}
Then I add the total avoidance vector to the AI's input direction and normalize the result:
inputDirection += avoidanceVector;
inputDirection.Normalize();
However, when i add this avoidance vector to my input direction, my ships exhibit a strange behavior where sometimes they will simply stop moving completely. commenting out the line where i add them together stops this behavior.
I'm really not sure what could be going wrong here, but I think it has to do with my approach altogether. Can anyone help me figure out a clean, simple way to make my ships steer away from other objects?
1
inv = (1 / ...
is too high and avoidance vector has too large magnitude). \$\endgroup\$if (hit.gameObject == gameObject) continue;
I'll edit my post to reflect that. Also, in regards to using1 / x
, the avoidance vector is actually too small unless the ship is very close to the collision, which makes sense - you don't need to steer away from something too hard unless you're about to hit it. \$\endgroup\$