UnityGameProjectsCode / RelianceGame / AI Control / Friendly Scripts / SearchState.cs
SearchState.cs
Raw
using AIMachineTools;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SearchState : State
{
    private static SearchState _instance; //only declared once


    private SearchState() //set instance to itself
    {
        if (_instance != null)
        {
            return;
        }

        _instance = this;
    }

    public static SearchState instance //creates the instance of the first state if it does not exist
    {
        get
        {
            if (_instance == null)
            {
                new SearchState();
            }

            return _instance;
        }
    }

    public override IEnumerator InState(AIMachine owner)
    {
        Waypoint currentWaypoint = null;
        Waypoint previousWaypoint = null;
        bool firstPointVisited = false;
        bool travelling = false;
        float timeWaited = 0f;

        owner.RemoveMarker();

        while (owner.botMachine.currentState == SearchState.instance)
        {
            if (!owner.disabled)
            {
                if (currentWaypoint == null)
                {
                    GameObject[] allWaypoints = GameObject.FindGameObjectsWithTag("Waypoint");
                    List<Waypoint> closeWaypoints = new List<Waypoint>();

                    if (allWaypoints.Length > 0)
                    {
                        while (currentWaypoint == null)
                        {
                            foreach (GameObject waypoint in allWaypoints)
                            {
                                if (Vector3.Distance(owner.gameObject.transform.position, waypoint.transform.position) <= 50)
                                {
                                    closeWaypoints.Add(waypoint.GetComponent<Waypoint>());
                                }
                            }

                            int random = Random.Range(0, closeWaypoints.Count);
                            Waypoint startingWaypoint = closeWaypoints[random];

                            if (startingWaypoint != null)
                            {
                                currentWaypoint = startingWaypoint;
                            }
                        }
                    }
                }

                if (firstPointVisited == true && travelling == false)
                {
                    Waypoint nextWaypoint = currentWaypoint.NextWaypoint(previousWaypoint);
                    previousWaypoint = currentWaypoint;
                    currentWaypoint = nextWaypoint;
                }

                owner.targetWaypoint = currentWaypoint.transform.position;

                foreach (GameObject bot in owner.friendlyBots)
                {
                    if (bot != null && !bot.GetComponent<AIAllyMachine>())
                    {
                        var target = bot.GetComponent<AIMachine>().targetWaypoint;

                        if (owner.targetWaypoint == target)
                        {
                            Debug.Log(bot + "has the same target as another bot");
                            Waypoint nextWaypoint = currentWaypoint.NextWaypoint(previousWaypoint);
                            previousWaypoint = currentWaypoint;
                            currentWaypoint = nextWaypoint;
                        }
                    }
                }

                if (owner.targetWaypoint != null)
                {
                    travelling = true;

                    if (Vector3.Angle(owner.transform.forward, owner.targetWaypoint - owner.transform.position) < 15)
                    {
                        MoveTurret(owner, owner.targetWaypoint);

                        owner.thisAgent.SetDestination(owner.targetWaypoint);

                        Debug.DrawLine(owner.transform.position, owner.targetWaypoint, Color.blue);

                        if (travelling && Vector3.Distance(owner.transform.position, owner.targetWaypoint) <= owner.markerDistance)
                        {
                            travelling = false;
                            firstPointVisited = true;
                        }
                    }
                    else
                        RotateBody(owner, owner.targetWaypoint);
                }

                if (owner.agentVelocity == new Vector3(0, 0, 0) && owner.targetWaypoint != null)
                {
                    timeWaited += Time.deltaTime;

                    if (timeWaited >= 5f)
                    {
                        Debug.Log(owner.displayName + " got stuck on a waypoint, generating a new point.");
                        Waypoint nextWaypoint = currentWaypoint.NextWaypoint(previousWaypoint);
                        previousWaypoint = currentWaypoint;
                        currentWaypoint = nextWaypoint;
                        timeWaited = 0;
                    }
                }

                if (owner.canSeeEnemy && owner.enemyObject != null)
                {
                    owner.botMachine.ChangeState(ChaseState.instance);
                    yield break;
                }
                else
                {
                    owner.canSeeEnemy = false;
                }

            }
            else
            {
                owner.thisAgent.SetDestination(owner.transform.position);
            }

            yield return null;
        }
    }

    private void RotateBody(AIMachine _owner, Vector3 navPoint) //called to have the bot rotate to face the waypoint before navigating to it
    {
        //declare variables that will be used to determine how to move the bot
        Quaternion targetRot = Quaternion.LookRotation(navPoint - _owner.transform.position);

        //rotate the bot over time to face the enemy
        _owner.transform.rotation = Quaternion.RotateTowards(_owner.transform.rotation, targetRot, Time.deltaTime * _owner.bodyRotateSpeed);

        //set the bots y euler angle so that it only moves on that transform
        _owner.transform.localEulerAngles = new Vector3(0, _owner.transform.localEulerAngles.y, 0);
    }

    private void MoveTurret(AIMachine _owner, Vector3 hitPos) //called to move the bots turret so that it faces whatever Vector3 is sent
    {
        //declare variables that will be used to determine how to move the turret
        Quaternion hitRot = Quaternion.LookRotation(hitPos - _owner.transform.position);
        Quaternion turretRot = Quaternion.LookRotation(hitPos - _owner.turretPos.transform.position);

        if (Vector3.Angle(_owner.turretPos.transform.forward, hitPos - _owner.turretPos.transform.position) > 5) //rotate the turret until it is facing within 5 degrees of the target
        {
            //rotate the turret over time to the target
            _owner.turretPos.transform.rotation = Quaternion.RotateTowards(_owner.turretPos.transform.rotation, turretRot, Time.deltaTime * _owner.turretRotateSpeed);

            //set the turrets y euler angle so that it only moves on that transform
            _owner.turretPos.transform.localEulerAngles = new Vector3(0, _owner.turretPos.transform.localEulerAngles.y, 0);
        }

        //rotate the barrel over time to the target
        _owner.barrelPos.transform.rotation = Quaternion.RotateTowards(_owner.barrelPos.transform.rotation, turretRot, Time.deltaTime * _owner.barrelMoveSpeed);

        //set the barrels y euler angle so that it only moves on that transform
        _owner.barrelPos.transform.localEulerAngles = new Vector3(0, _owner.barrelPos.transform.localEulerAngles.y, 0);
    }
}