3
\$\begingroup\$

I am currently working on a simple obstacle avoidance system in unity. I have a player and a school of Ai fish that are traveling in a fixed direction (Down-Right). While swimming, I want the Ai fish to keep away from the player, and also keep away from incoming obstacles. I first thought I should use a boid flocking algorithm, but it may be overkill for what I need as I am trying to limit computation to as low as possible since it will need to run on a mobile device. the fish do not need to avoid each other and they simply need to head toward the fixed direction. Other notes: I can't use unity's NavMesh system since I am using 2d physics and obstacles will be random at runtime.

My issue is that I do not know how to efficiently steer the AI when there are multiple obstacles and players in the proximity. I have something working(Below), but I am manually steering it when it gets too close but this won't work when I have multiple obstacles to avoid within their proximity. Could someone steer (ha) me in the right direction on how to approach this?

Thank You

Example of Current System

Below is the class I made for the Ai fish:

public class FishMoveTest : MonoBehaviour {
public float Speed;
Rigidbody2D rb;
public float MinSpeed;
public float MaxSpeed;
public float DisableDistance;
private float DistanceFromPlayer;
public GameObject Player;
 Material NormalMat;
public Material CollideMat;
 MeshRenderer MeshRend;
public UnderwaterObstacle _UnderwaterObstacle;
public float AvoidDistance;
public float SteerSpeed;
float DistanceFromObstacle;
// Use this for initialization
void Awake () {
    MeshRend =  GetComponent<MeshRenderer> ();
    NormalMat = MeshRend.material;
    rb = GetComponent<Rigidbody2D> ();
    Speed = Random.Range (MinSpeed, MaxSpeed);
}

// Update is called once per frame
void FixedUpdate () {
    DistanceFromObstacle = Vector3.Distance(transform.position, _UnderwaterObstacle.Obstacle.position);
    if (DistanceFromObstacle < AvoidDistance) {
        CastObstacleRay ();
        if (MeshRend.material != CollideMat) {
            MeshRend.material = CollideMat;
        }
        if (transform.position.y > _UnderwaterObstacle.Obstacle.position.y) {
            //Move Up-Right;
            rb.velocity = Vector3.Lerp(rb.velocity,new Vector3 (0.5f, 0.5f, 0) * Speed,SteerSpeed);

        } else {
            //Move Down
            rb.velocity = Vector3.Lerp(rb.velocity,new Vector3 (0, -1, 0) * Speed,SteerSpeed);
        }
    } else {

        rb.velocity = Vector3.Lerp(rb.velocity,new Vector3 (0.5f, -0.5f, 0) * Speed,SteerSpeed);
        if (MeshRend.material != NormalMat) {
            MeshRend.material = NormalMat;
        }
    }
}
\$\endgroup\$
7
  • \$\begingroup\$ CastObstacleRay(), where is it? \$\endgroup\$ Commented Aug 3, 2017 at 6:42
  • \$\begingroup\$ that is just a debug ray (green rays in Gif) that I call if it gets too close. I did not include it because it was not essential to the actual system. public void CastObstacleRay(){ Vector3 RayDir = -(transform.position + _UnderwaterObstacle.Obstacle.position).normalized; Debug.DrawRay(transform.position, RayDir * DistanceFromObstacle, Color.green); } \$\endgroup\$ Commented Aug 3, 2017 at 12:09
  • \$\begingroup\$ For a swarm like this, you might benefit from generating a flow field over your space, then let each fish follow the local flow, rather than rely on each fish checking its local obstacles and planning independently. \$\endgroup\$ Commented Aug 3, 2017 at 12:50
  • 1
    \$\begingroup\$ @JohnHamilton: Unity's attractors apply local forces, without any knowledge of larger-scale structures or goals. They won't guide the school in pathing around a collection of obstacles like a maze the way that a flow field can. \$\endgroup\$ Commented Aug 4, 2017 at 12:25
  • 1
    \$\begingroup\$ The mesh implementation is certainly possible, but again doesn't solve the same problem. A gravitational heightmap without the goal-seeking behaviour described at the link can have local minima - valleys between obstacles where fish would get stuck because going any direction means climbing uphill. A goal-based pathfinding flow field will find the shortest route to the goal from each point that can reach it, even if it means passing through a bottleneck between two obstacles/repulsors. \$\endgroup\$ Commented Aug 4, 2017 at 13:07

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.