Trouble with Boids style flocking implementation

So what I’m trying to do is build an AI that will act similarly to a boids AI, but not need a separate flock manager script, and I also want it to avoid obstacles other than its flock mates. Currently I have a have functions that find the vector away from obstacles, a function that finds the center of the rest of the flock, and a function that finds the direction towards the target, all of those functions work. The trouble I’m having is with putting all the vectors together and getting the AI to go the right direction. (GoVectorDirection being the function that does this)


using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class swarmBrain : MonoBehaviour {


    public List<GameObject> closeAllies = new List<GameObject>();
    public List<GameObject> closeObstacles = new List<GameObject>();
    public float swarmRange = 5f;
    public float avoidDistance = 1f;
    public Vector2 swarmCenter;
    public string targetTag;
    public GameObject target;
    public Vector2 avoidVector;
    public Vector2 centerVector;
    public Vector2 targetVector;
    public Vector2 aimDirection;
    public Vector2 changeVector;
    // Use this for initialization
    void Start () {
        target = GameObject.FindGameObjectWithTag (targetTag);
    }

    // Update is called once per frame
    void Update () {
        getLocalAllies ();
        getLocalObstacles ();
        getSwarmCenter ();
        goVectorDirection ();

    }

    void GetLocalAllies(){
        GameObject[] allAllies = null;
        if ( GameObject.FindGameObjectsWithTag (this.gameObject.tag) != null){
            allAllies = GameObject.FindGameObjectsWithTag (this.gameObject.tag);
        }
        closeAllies.Clear ();
        if (allAllies != null) {
            foreach (GameObject g in allAllies) {
                float distance = Vector2.Distance (this.gameObject.transform.position, g.transform.position);
                if (distance < swarmRange && g != this.gameObject){
                    closeAllies.Add (g);
                }
            }
        }
    }

    void GetLocalObstacles(){
        avoidVector = Vector2.zero;
        Collider2D[] Obstacles = Physics2D.OverlapCircleAll (transform.position, swarmRange);
        closeObstacles.Clear ();
        if (Obstacles != null) {
            foreach (Collider2D o in Obstacles) {
                Vector2 collisionPoint = o.bounds.ClosestPoint (transform.position);
                float distance = Vector2.Distance (this.gameObject.transform.position, collisionPoint);
                if (distance < avoidDistance && o.gameObject != this.gameObject) {
                    closeObstacles.Add (o.gameObject);
                    Vector2 a = (Vector2)this.transform.position - collisionPoint;
                    avoidVector = avoidVector + a;
                }
            }
            avoidVector = avoidVector.normalized;
        }
    }

    void GetSwarmCenter(){
        if (closeAllies != null) {
            Vector2 tempCenter = Vector2.zero;
            foreach (GameObject g in closeAllies) {
                tempCenter += (Vector2)g.transform.position;
            }
            //tempCenter += (Vector2)transform.position;
            swarmCenter = tempCenter/ (closeAllies.Count);
            centerVector = (swarmCenter - (Vector2)transform.position).normalized;
        }
    }

    void GoVectorDirection(){
        Vector2 vectorToTarget = (Vector2)(target.transform.position - this.transform.position);
        Vector2 vectorToSwarm;

        if (closeAllies.Count > 0) {
            vectorToSwarm = swarmCenter - (Vector2)this.transform.position;
            changeVector = (vectorToTarget.normalized + vectorToSwarm.normalized + avoidVector.normalized)/3;
        } else {
            changeVector = (vectorToTarget.normalized + avoidVector.normalized)/2;
        }
        changeVector = changeVector.normalized;
        aimDirection =  changeVector  + (Vector2)transform.position ;

        if(aimDirection != Vector2.zero){
            GeneralFunctions.TurnToObject (aimDirection, this.transform.gameObject, 1);
        }

        transform.Translate (gameObject.transform.up * 0.1f);

    }

    void OnDrawGizmos(){
        Gizmos.color = Color.white;
        Gizmos.DrawWireSphere (transform.position, swarmRange);

        Gizmos.color = Color.blue;
        Gizmos.DrawSphere (swarmCenter, 0.1f);
        Gizmos.DrawRay (transform.position, centerVector);

        Gizmos.color = Color.red;
        Gizmos.DrawRay (transform.position, avoidVector);

        Gizmos.color = Color.green;
        if (target != null) {
            Gizmos.DrawLine (transform.position, aimDirection);
            Gizmos.DrawLine (aimDirection, target.transform.position);
            Gizmos.DrawSphere (aimDirection, 0.25f);
        }

        Gizmos.color = Color.magenta;
        //Gizmos.DrawSphere (aimDirection, 1);
        Gizmos.DrawRay(transform.position, changeVector);
    }

}

edit: added code tags and updated function casing

If you don’t do this (^), nobody’s going to read it

1 Like

I feel I should also mention that methods (functions) should use PascalCase not camelCase.