예제 #1
0
    void Awake()
    {
        //Instantiate Boids
        boidsList  = new List <GameObject>();
        statusList = new List <BoidStatus>();
        hailList   = HailController.hailList; // Get list from HailController

        for (int i = 0; i < boidCount; ++i)
        {
            for (int j = 0; j < boidCount; ++j)
            {
                GameObject newBoid = new GameObject();
                newBoid.transform.parent = gameObject.transform;
                newBoid.name             = "Boid No." + (i * boidCount + j).ToString();

                GameObject instPrefab = Instantiate(boidPrefab); // insantiate the bird
                instPrefab.transform.parent = newBoid.transform;

                Vector3    startingPos = new Vector3(Random.Range(-2f, -2.5f), Random.Range(0.5f, 1f), Random.Range(-2f, -2.5f));
                BoidStatus status      = new BoidStatus();
                status.position              = startingPos + goalMarker.transform.position;
                newBoid.transform.position   = status.position;
                newBoid.transform.localScale = new Vector3(.25f, .25f, .25f);
                status.boidObject            = newBoid;
                boidsList.Add(newBoid);
                statusList.Add(status);
            }
        }
        direction = new Vector3[statusList.Count];
        //hide the original prefab
        boidPrefab.SetActive(false);
    }
예제 #2
0
    // Start is called before the first frame update
    void Start()
    {
        statusList = new List <BoidStatus>();
        for (int i = 0; i < boidCount; ++i)
        {
            for (int j = 0; j < boidCount; ++j)
            {
                GameObject newBoid = new GameObject();
                newBoid.transform.parent = gameObject.transform;
                newBoid.name             = "Boid No." + (i * boidCount + j).ToString();

                GameObject instPrefab = Instantiate(boidPrefab);
                instPrefab.transform.parent = newBoid.transform;

                Vector3    startingPos = new Vector3((float)j - 4, (float)-3, (float)i - 4);
                BoidStatus status      = new BoidStatus();
                status.position                         = startingPos + goalMarker.transform.position;
                newBoid.transform.position              = status.position;
                status.boidObject                       = newBoid;
                status.boidObject.transform.localScale *= .25f;
                // status.velocity = new Vector3(0, 0, 0);
                statusList.Add(status);
            }
        }
        boidPrefab.SetActive(true);
    }
예제 #3
0
    Vector3 calculate_separation(BoidStatus boid)
    {
        int neighbour_count = 0;
        //int terrain = 0;
        Vector3 point    = boid.position;
        Vector3 velocity = new Vector3(0, 0, 0);

        for (int i = 0; i < statusList.Count; ++i)
        {
            if (statusList[i] != boid)
            {
                if (Vector3.Distance(statusList[i].position, point) < detection_radius)
                {
                    velocity += statusList[i].position - point;
                    neighbour_count++;
                }
            }
        }

        /*if(point.x >= 0 && point.z >= 0 && point.x < terrainMap.subdivision && point.z < terrainMap.subdivision) {
         *  velocity.y += terrainMap.perlinHeight[(int)point.z , (int)point.x] - point.y;
         *  terrain++;
         *  Debug.Log("Got here");
         * }*/
        if (neighbour_count != 0)
        {
            velocity /= neighbour_count;
            velocity *= -1;
        }
        return(velocity.normalized);
    }
예제 #4
0
    // Update is called once per frame
    void Update()
    {
        for (int i = 0; i < statusList.Count; ++i)
        {
            BoidStatus status = statusList[i];
            status.velocity = Vector3.zero;
            Vector3 alignment      = align_velocity(status);
            Vector3 cohesion       = calculate_cohesion(status);
            Vector3 separation     = calculate_separation(status);
            Vector3 leader         = goalMarker.transform.position - status.position;
            Vector3 terrain_colide = Vector3.zero;

            float x = status.position.x;
            float z = status.position.z;
            if (x < 5f && z < 5f && x >= -5f && z >= -5f)
            {
                x = (x + 5f) * 25f;
                z = (z + 5f) * 25f;
                if (status.position.y <= terrainMap.perlinHeight[(int)x, (int)z] + 0.3f)
                {
                    status.position.y += terrainMap.perlinHeight[(int)x, (int)z];
                }
            }

            status.velocity += alignment * 1.5f + cohesion * 1.5f + separation * 6f + leader;
            status.velocity  = status.velocity.normalized;
            status.position += status.velocity * .15f;

            //float noise_dist;

            //terrain collision prevention

            /*if(status.position.x < terrainMap.subdivision && status.position.z < terrainMap.subdivision && status.position.x >= 0 && status.position.z >= 0) {
             *  status.position.y += terrainMap.perlinHeight[(int)status.position.x, (int)status.position.z];
             *  /* noise_dist = goalMarker.transform.position.y - terrainMap.perlinHeight[(int)status.position.x, (int)status.position.z];
             *  if((status.position.y * -1) >= noise_dist) {
             *      status.position.y += terrainMap.perlinHeight[(int)status.position.x, (int)status.position.z];
             *  }*/
            //if(status.position.y <= terrainMap.perlinHeight[(int)status.position.z, (int)status.position.x]) {

            //status.position.y += (terrainMap.perlinHeight[(int)status.position.z, (int)status.position.x] - status.position.y) + 0.1f;
            //Debug.Log("got here");
            //}
            //}

            status.boidObject.transform.LookAt(status.position);
            status.boidObject.transform.Rotate(0, 90, 90);
            status.boidObject.transform.position = status.position;

            //status.boidObject.transform.forward = Vector3.Normalize(goalMarker.transform.position - status.boidObject.transform.position);
            statusList[i] = status;
        }
    }
예제 #5
0
    // next 3 functions inspired by: https://gamedevelopment.tutsplus.com/tutorials/3-simple-rules-of-flocking-behaviors-alignment-cohesion-and-separation--gamedev-3444
    Vector3 align_velocity(BoidStatus boid)
    {
        Vector3 point           = boid.position;
        int     neighbour_count = 0;
        Vector3 velocity        = new Vector3(0, 0, 0);

        for (int i = 0; i < statusList.Count; ++i)
        {
            if (statusList[i] != boid)
            {
                if (Vector3.Distance(statusList[i].position, point) < detection_radius)
                {
                    velocity += statusList[i].velocity;
                    neighbour_count++;
                }
            }
        }
        if (neighbour_count != 0)
        {
            velocity /= neighbour_count;
        }
        return(velocity.normalized);
    }
예제 #6
0
    // Update is called once per frame
    void Update()
    {
        for (int i = 0; i < statusList.Count; ++i)
        {
            BoidStatus        status    = statusList[i];
            List <BoidStatus> neighbors = new List <BoidStatus>();

            Vector3 V1 = new Vector3(0, 0, 0); // Separation
            Vector3 V2 = new Vector3(0, 0, 0); // Alignment
            Vector3 V3 = new Vector3(0, 0, 0); // Cohesion
            Vector3 V4 = new Vector3(0, 0, 0); // Predator Avoidance

            // Separation
            for (int j = 0; j < statusList.Count - 1; ++j)
            {
                BoidStatus nextStatus = statusList[j]; // Check every boid in list

                Vector3 boidVec  = Vector3.Normalize(status.boidObject.transform.position - nextStatus.boidObject.transform.position);
                float   distance = Vector3.Distance(status.boidObject.transform.position, nextStatus.boidObject.transform.position);
                // if distance is 0 then boids are the same
                if (distance <= separation && distance > 0) // Boids are too close
                {
                    V1 = (boidVec / distance) * separation;
                    status.boidObject.transform.position += V1 * Time.deltaTime * speed;

                    neighbors.Add(nextStatus); // Keep track of all neighbors
                }
                else // They are an appropriate distance away
                {
                    status.boidObject.transform.position += new Vector3(0f, 0f, 0f) * speed * Time.deltaTime;
                }
            }

            // Alignment
            V2 = BoidDir(status.position);

            // Cohesion
            Vector3 centerVec = new Vector3(0, 0, 0);
            V3 = new Vector3(0, 0, 0);
            for (int j = 0; j < neighbors.Count; ++j)
            {
                centerVec += goalMarker.transform.position;
            }
            centerVec = centerVec / neighbors.Count;
            if (centerVec.magnitude <= cohesion)
            {
                V3 = Vector3.Normalize(centerVec / centerVec.magnitude);
                status.boidObject.transform.position += V3 * Time.deltaTime * speed;
            }

            // Predator Avoidance, similar to separation -> separate from predator arrow
            Vector3 predVec   = Vector3.Normalize(status.boidObject.transform.position - predator.transform.position);
            float   pDistance = Vector3.Distance(predator.transform.position, status.boidObject.transform.position);

            if (pDistance <= predDistance && pDistance > 0) // change boids direction to keep away from predator
            {
                V4             = (predVec / pDistance) * predSeparation;
                direction[i]   = Vector3.Normalize(V4 - status.boidObject.transform.position);
                predSeparation = predSeparation + .2f;
            }
            else // predator is far enough away
            {
                predSeparation = 1.0f;
                direction[i]   = Vector3.Normalize(V2 - status.boidObject.transform.position);
            }

            // Check for hail hit
            for (int j = 0; j < hailList.Count; ++j)
            {
                Vector3 boid = status.boidObject.transform.position;
                Vector3 hail = hailList[j].hailObject.transform.position;
                if (Vector3.Distance(boid, hail) <= .1f && hail.y >= boid.y)
                {
                    float hitDiff = Mathf.Abs(direction[i].y - hailList[j].fallingDirection.y);
                    //direction[i] = Vector3.Normalize(new Vector3(direction[i].x, direction[i].z - hitDiff, direction[i].z));

                    status.boidObject.transform.position = Vector3.Normalize(new Vector3(direction[i].x, 0, direction[i].z));// When a piece of hail hits a boid then it falls to the same direction as the hail peice.
                }
            }
            status.boidObject.transform.up        = direction[i];
            status.boidObject.transform.position += direction[i] * Time.deltaTime * speed;

            statusList[i] = status;
        }
    }