Wednesday, December 13, 2017

Seagull Ai






Here is an ai for seagulls. They fly around, land, and take off similar to actual birds. A world can easily be populated with these birds to bring more "life" into the environment.

Full Code Here




// Code by Nick Barber

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

public class SeagullAi : MonoBehaviour {

    float RNG;
    Vector3 FlyingDirection;
    Vector3 landingPoint;
    Vector3 LandingRot;
    Vector3 TakeoffDirection;
    bool flying;
    bool landing;
    public float Speed;
    public float YawSpeed;
    public float PitchSpeed;
    public Transform player;
    void Start(){
        StartCoroutine(Timer());
    }
    IEnumerator Timer(){ //run every second, randomly generates a vector and float for use in navigation and rng
        do{
            RaycastHit hit;
            Vector3 groundview = transform.TransformDirection(Vector3.down);
            float newyaw;
            if (transform.position.y < 8 || Physics.Raycast(transform.position, groundview, out hit, 20)){ //too close to ground
                newyaw = -10.0f;
            }
            else if (transform.position.y > 80){ // too high
                newyaw = 5.0f;
            }
            else{
                newyaw = Random.Range(-5.0f, 5.0f);
            }
            FlyingDirection = new Vector3(newyaw, Random.Range(0, 360),0);
            RNG = Random.Range(0, 100); //used for percent chance
            yield return new WaitForSeconds(1);
        } while (1==1);
    }

    void FixedUpdate(){
        if (flying){
            Speed = 10;
            if (RNG > 90 && transform.position.y > 20 && Vector3.Distance(transform.position, player.position) > 20){ //randomly choose a landing point, if the timing is correct, you arnt near the player, and you are high enough in the sky
                FindLandingPoint();
                GetComponent().Play("Armature|Wing Flap");
            }
            //Flying maths
            Vector3 NewAngle = new Vector3(Mathf.LerpAngle(transform.eulerAngles.x, FlyingDirection.x, Time.deltaTime * PitchSpeed), Mathf.LerpAngle(transform.eulerAngles.y, FlyingDirection.y, Time.deltaTime * YawSpeed), 0);
            transform.eulerAngles = NewAngle;
            transform.Translate(Vector3.forward * Time.deltaTime * Speed);
        }
        else if (landing){
            Speed = 8;
            if (Vector3.Distance(transform.position, landingPoint) > 0.1f){ //rotate and fly towards desired landing position while you are not close enough to land
                Vector3 Target = landingPoint - transform.position;
                Quaternion ToRotation = Quaternion.FromToRotation(Vector3.forward, Target);
                transform.rotation = Quaternion.Lerp(transform.rotation, ToRotation, Time.deltaTime * 1f);
                transform.Translate(Vector3.forward * Time.deltaTime * Speed);                
            }
            else{ //stick to the ground where you wanted to land
                GetComponent().Play("Armature|land");
                transform.eulerAngles = LandingRot;
                transform.position = landingPoint;
                if (RNG > 95 || Vector3.Distance(transform.position, player.position) < 10){ //wait to takeoff, can be intrupted by a player "shooing" you away
                    GetTakeOffDirection();
                    landing = false;
                }
            }

        }
        else{ //take off
            Speed = 10;
            if (Vector3.Distance(transform.position, landingPoint) < 20){
                transform.rotation = Quaternion.LookRotation(TakeoffDirection);
                transform.Translate(Vector3.forward * Time.deltaTime * Speed);
            }
            else{
                flying = true;
                landing = false;
            }
        }
    }
    
    void FindLandingPoint(){ //search for a landing point
        Vector3 desiredLandingPoint;
        int Distance= 50;
        RaycastHit Hit3;
        desiredLandingPoint = new Vector3(Random.Range(transform.position.x - Distance, transform.position.x + Distance), transform.position.y, Random.Range(transform.position.z - Distance, transform.position.z + Distance));
        Debug.DrawRay (desiredLandingPoint, Vector3.down * 100, Color.blue); 
        if (Physics.Raycast(desiredLandingPoint, Vector3.down, out Hit3, 100)){
            if (Hit3.transform.tag != "UnderWater" && Hit3.transform.tag != "Water" && Hit3.transform.tag != "Boat" && Hit3.transform.tag != "PickUp" && Hit3.transform.tag != "Untagged"){
                    landingPoint = Hit3.point;
                    LandingRot = Hit3.normal;
                    flying = false;
                    landing = true;
                    return;
            }
        }
        return;
    }

    void GetTakeOffDirection(){ //find a direction that is free to take off
        RaycastHit hit;
        TakeoffDirection = transform.TransformDirection(Vector3.forward);
        TakeoffDirection.y += 0.5f;
        Vector3 Above = transform.position;
        Above.y += 1;
        int timesTried = 0;
        do {
            Debug.DrawRay (Above, TakeoffDirection * 50, Color.red); 
            if (Physics.Raycast(Above, TakeoffDirection, out hit, 50)){
                
                    TakeoffDirection = Quaternion.Euler(0, -10, 0) * TakeoffDirection;
            }
            else{                
                GetComponent().Play("Armature|Wing Flap");
                flying = false;
                landing = false;
                return;
            }
            timesTried++;
        } while (timesTried < 100);
        print(name + " is stuck!");
        Destroy(gameObject);
        return;
    }
}



No comments:

Post a Comment