예제 #1
0
    // Update is called once per frame
    void FixedUpdate()
    {
        // timer to control change in wander and digestion applications
        if (Time.time > timer)
        {
            timer = Time.time + thinktime;
            float rndm_angle = 360 * Random.value;
            radrndm_angle = Mathf.Deg2Rad * rndm_angle;
            fed           = Mathf.Min(((fed * digestionrate) + food), appettite);
            hunger        = (1f - (fed / appettite));
            food          = 0;
        }
        //set wander direction
        float x = (wander_circlediameter / 2) * Mathf.Cos(radrndm_angle) + (transform.position.x + Mathf.Clamp(transform.GetComponent <Rigidbody>().velocity.x, -maxvel, maxvel));
        float y = (wander_circlediameter / 2) * Mathf.Sin(radrndm_angle) + (transform.position.y + Mathf.Clamp(transform.GetComponent <Rigidbody>().velocity.y, -maxvel, maxvel));
        float z = (wander_circlediameter / 2) * Mathf.Sin(radrndm_angle) + (transform.position.z + Mathf.Clamp(transform.GetComponent <Rigidbody>().velocity.z, -maxvel, maxvel));

        wander_dir.Set(x, (y), z);
        //////// find boids to hunt
        if (boids == null)
        {
            boids = GameObject.FindGameObjectsWithTag("boid");
        }
        for (int boid_index = 0; boid_index < boids.Length; boid_index++)
        {
            Vector3 fishpos = boids [boid_index].transform.position;
            if (closestfish == null)
            {
                closestfish = boids [boid_index];
            }
            boid_script r = (boid_script)boids [boid_index].GetComponent(typeof(boid_script));
            // if state not dead hunt
            if (r.returnstate() != 2)
            {
                if (Vector3.Distance(transform.position, fishpos) < Vector3.Distance(transform.position, closestfish.transform.position))
                {
                    closestfish = boids [boid_index];
                }
            }
        }
        // sets fsm to hunt if hungry
        if (hunger > hungerlimit)
        {
            val = 1;
        }
        else
        {
            val = 0;
        }

        ////////////////////////// fsm
        switch (fsmArray [currentState, val + 1])
        {
        case 0:
            Debug.Log("Wander");
            currentState = 0;
            break;

        case 1:
            Debug.Log("Hunt");
            currentState = 1;
            break;

        default:
            break;
        }
        // if hunting  moves towards fish and attacks
        if (currentState == 1)
        {
            boid_script r = (boid_script)closestfish.GetComponent(typeof(boid_script));
            if (r.returnstate() != 2)
            {
                Vector3 fishpredpos = closestfish.transform.position + 0.5f * Vector3.Distance(transform.position, closestfish.transform.position) * closestfish.GetComponent <Rigidbody>().velocity;
                GetComponent <Rigidbody>().AddForce(fishpredpos - transform.position, ForceMode.Force);
                Debug.DrawLine(transform.position, closestfish.transform.position, Color.magenta);
                Debug.DrawLine(closestfish.transform.position, fishpredpos, Color.cyan);

                if (Vector3.Distance(transform.position, closestfish.transform.position) < attackdistance)
                {
                    food = r.eaten();
                }
            }
            // otherwise apply wander force
        }
        else if (currentState == 0)
        {
            GetComponent <Rigidbody>().AddForce(wander_dir - transform.position, ForceMode.Force);
        }
        /////////////////////////////////////////////////////////////////////////////////
        // if the boids list is null
        if (sharkboids == null)
        {
            // get the other boids
            sharkboids = GameObject.FindGameObjectsWithTag("shark");
        }
        else
        {
            // deal with the boid escape case - must stay within simulation_radius
            if (Vector3.Distance(simulation_centre, transform.position) > simulation_radius - 2)
            {
                if (Vector3.Distance(simulation_centre, transform.position) > simulation_radius)
                {
                }
                float radius_scalar = Vector3.Distance(simulation_centre, transform.position) - (simulation_radius - 2) / 2;
                GetComponent <Rigidbody>().AddForce(Vector3.ClampMagnitude(simulation_centre - transform.position * radius_scalar, max_wallvel), ForceMode.Force);
            }
        }
        // swarm control for shark boids
        for (int boid_index = 0; boid_index < sharkboids.Length; boid_index++)
        {
            // position of boid at index
            Vector3    pos = sharkboids [boid_index].transform.position;
            Quaternion rot = sharkboids [boid_index].transform.rotation;
            // the distance
            float dist = Vector3.Distance(transform.position, pos);

            // if not this boid
            if (dist > 0f)
            {
                // if within separation
                if (dist <= separation_distance)
                {
                    // compute the scale of separationt
                    float scale = separation_strength / dist;
                    // add a separation force between this boid and its neighbour
                    GetComponent <Rigidbody>().AddForce(Vector3.Normalize(transform.position - pos) * scale, ForceMode.Force);
                    //Debug.DrawLine (transform.position, transform.position + Vector3.Normalize (transform.position - pos), Color.white);
                }
                if (dist < cohesion_distance && dist > separation_distance)                                                   // if within cohesive distance but not separation
                // compute the cohesive position
                {
                    cohesive_number++;
                    cohesion_pos = cohesion_pos + pos;
                    // alignment - small rotations are applied based on the alignments of the neighbours
                    transform.rotation = Quaternion.RotateTowards(transform.rotation, rot, 1f);
                }
            }
        }
        if (cohesive_number > 1)
        {
            cohesion_pos = cohesion_pos * (1 / cohesive_number);
            //add cohesive force
            // compute the scale
            cohesive_force = (cohesion_strength / Vector3.Distance(cohesion_pos, transform.position)) * (cohesion_pos - transform.position);
            // apply force
            GetComponent <Rigidbody>().AddForce(cohesive_force, ForceMode.Force);
            Debug.DrawLine(transform.position, cohesion_pos, Color.yellow);
            // zero the cohesion vector
            cohesion_pos    = transform.position;
            cohesive_number = 1;
        }
        // clamp magitude and rotate towards center of velocity
        transform.GetComponent <Rigidbody>().velocity = Vector3.ClampMagnitude(transform.GetComponent <Rigidbody>().velocity, maxvel);
        Debug.DrawLine(transform.position, wander_dir, Color.blue);
        Debug.DrawLine(transform.position, transform.position + transform.GetComponent <Rigidbody>().velocity, Color.red);
        transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.LookRotation(transform.position + transform.GetComponent <Rigidbody>().velocity), 20f);
    }
예제 #2
0
    void FixedUpdate()
    {
        //fsm to control fish states
        switch (fsmArray [currentState, val + 1])
        {
        case 0:
            Debug.Log("Wander");
            currentState = 0;
            GetComponent <Renderer>().material.color = Color.gray;
            break;

        case 1:
            Debug.Log("Flee");
            currentState = 1;
            GetComponent <Renderer>().material.color = Color.white;
            break;

        case 2:
            Debug.Log("Dead");
            currentState = 2;
            GetComponent <Renderer>().material.color = Color.black;
            break;

        default:
            break;
        }
        //when fish is dead controls actions
        if (currentState == 2)
        {
            if (Time.time < deadtimer)
            {
                return;
            }
            else
            {
                val = 2;
                return;
            }
        }

        ///////////////////////////////////////////////////////////////////////////
        //deals with each shark determining fear and if action should be taken
        if (sharkboids == null)
        {
            sharkboids = GameObject.FindGameObjectsWithTag("shark");
            if (fears == null)
            {
                fears = new float[sharkboids.Length];
            }
        }
        else
        {
            for (int sharkboid_index = 0; sharkboid_index < sharkboids.Length; sharkboid_index++)
            {
                Vector3 sharkpos = sharkboids [sharkboid_index].transform.position;
                fears [sharkboid_index] = Mathf.Min(comfortdistance / Vector3.Distance(transform.position, sharkpos), 1);
                if (fears [sharkboid_index] == 1)
                {
                    val = 0;
                }
                else
                {
                    val = 1;
                }
                if (currentState == 1)
                {
                    //determines predator predicated pos and adds force away from position
                    Vector3 predator_predicted_pos = sharkpos + .5f * Vector3.Distance(transform.position, sharkpos) * sharkboids [sharkboid_index].GetComponent <Rigidbody>().velocity;
                    GetComponent <Rigidbody>().AddForce(Vector3.ClampMagnitude(predator_predicted_pos - transform.position, 50f), ForceMode.Force);
                    Debug.DrawLine(sharkpos, predator_predicted_pos, Color.white);
                }
//			}
            }
        }

        /////////////////////////////////////////////////////////////////////////////////
        // if the boids list is null
        if (boids == null)
        {
            // get the other boids
            boids = GameObject.FindGameObjectsWithTag("boid");
        }
        else
        {
            // deal with the boid escape case - must stay within simulation_radius
            if (Vector3.Distance(simulation_centre, transform.position) > simulation_radius - 2)
            {
                if (Vector3.Distance(simulation_centre, transform.position) > simulation_radius)
                {
                }
                //push boids back into simulation the closer to the wall the more force is given
                float radius_scalar = Vector3.Distance(simulation_centre, transform.position) - (simulation_radius - 2) / 2;
                GetComponent <Rigidbody>().AddForce(Vector3.ClampMagnitude(simulation_centre - transform.position * radius_scalar, max_wallvel), ForceMode.Force);
            }
        }

        for (int boid_index = 0; boid_index < boids.Length; boid_index++)
        {
            boid_script r = (boid_script)boids [boid_index].GetComponent(typeof(boid_script));
            if (r.returnstate() != 2)
            {
                // position of boid at index
                Vector3    pos = boids [boid_index].transform.position;
                Quaternion rot = boids [boid_index].transform.rotation;
                // the distance
                float dist = Vector3.Distance(transform.position, pos);

                // if not this boid
                if (dist > 0f)
                {
                    // if within separation
                    if (dist <= separation_distance)
                    {
                        // compute the scale of separationt
                        float scale = separation_strength / dist;
                        // add a separation force between this boid and its neighbour
                        GetComponent <Rigidbody>().AddForce(Vector3.Normalize(transform.position - pos) * scale, ForceMode.Force);
                        //Debug.DrawLine (transform.position, transform.position + Vector3.Normalize (transform.position - pos), Color.white);
                    }
                    if (dist < cohesion_distance && dist > separation_distance)                                                               // if within cohesive distance but not separation
                    // compute the cohesive position
                    {
                        cohesive_number++;
                        cohesion_pos = cohesion_pos + pos;
                        // alignment - small rotations are applied based on the alignments of the neighbours
                        transform.rotation = Quaternion.RotateTowards(transform.rotation, rot, 1f);
                    }                                                             //else if(dist >= cohesion_distance){
                }
            }
        }
        if (cohesive_number > 1)
        {
            cohesion_pos = cohesion_pos * (1 / cohesive_number);
            //add cohesive force
            // compute the scale
            cohesive_force = (cohesion_strength / Vector3.Distance(cohesion_pos, transform.position)) * (cohesion_pos - transform.position);
            // apply force
            GetComponent <Rigidbody>().AddForce(cohesive_force, ForceMode.Force);
            Debug.DrawLine(transform.position, cohesion_pos, Color.yellow);
            // zero the cohesion vector
            cohesion_pos    = transform.position;
            cohesive_number = 1;
        }
        //timer controls creates random angle
        if (Time.time > timer)
        {
            timer = Time.time + fishthinktime;
            float rndm_angle = 360 * Random.value;
            radrndm_angle = Mathf.Deg2Rad * rndm_angle;
        }
        //sets coords for wander circle
        float x = (wander_circlediameter / 2) * Mathf.Cos(radrndm_angle) + (transform.position.x + Mathf.Clamp(transform.GetComponent <Rigidbody>().velocity.x, -maxvel, maxvel));
        float y = (wander_circlediameter / 2) * Mathf.Sin(radrndm_angle) + (transform.position.y + Mathf.Clamp(transform.GetComponent <Rigidbody>().velocity.y, -maxvel, maxvel));
        float z = (wander_circlediameter / 2) * Mathf.Sin(radrndm_angle) + (transform.position.z + Mathf.Clamp(transform.GetComponent <Rigidbody>().velocity.z, -maxvel, maxvel));

        wander_dir.Set(x, (y), z);
        // adds force for wander
        GetComponent <Rigidbody>().AddForce(wander_dir - transform.position, ForceMode.Force);
        Debug.DrawLine(transform.position, wander_dir, Color.blue);
        Debug.DrawLine(transform.position, transform.position + transform.GetComponent <Rigidbody>().velocity, Color.red);
        transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.LookRotation(transform.position + transform.GetComponent <Rigidbody>().velocity), 6f);
// clamps velocity of fish
        transform.GetComponent <Rigidbody>().velocity = Vector3.ClampMagnitude(transform.GetComponent <Rigidbody>().velocity, maxvel);
    }