UnityGameProjectsCode / RelianceGame / AI Control / Enemy Scripts / EnemyChaseState.cs
EnemyChaseState.cs
Raw
using EnemyAIMachineTools;
using System.Collections;
using UnityEngine;

public class EnemyChaseState : EnemyState
{
    private static EnemyChaseState _instance; //only declared once

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

        _instance = this;
    }

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

            return _instance;
        }
    }

    public override IEnumerator InState(EnemyAIMachine owner)
    {
        float timeBeforeAttack = 2.0f;
        float timeSinceEnteredState = 0.0f;

        while (owner.botMachine.currentState == EnemyChaseState.instance)
        {
            if (!owner.disabled)
            {
                if (timeSinceEnteredState < timeBeforeAttack)
                    timeSinceEnteredState += Time.deltaTime;

                if (owner.enemyObject == null) //if the enemy is gone, go back to search
                {
                    owner.health = null;
                    if (owner.insideNormalSearch)
                        owner.botMachine.ChangeState(EnemySearchState.instance);
                    else if (owner.insideDefend)
                        owner.botMachine.ChangeState(EnemyMoveToState.instance);
                    else if (owner.insidePartner)
                        owner.botMachine.ChangeState(EnemyPartnerState.instance);
                    yield break;
                }

                if (owner.enemyObject != null) //if the enemy is still around, go after it
                {
                    if (Vector3.Angle(owner.transform.forward, owner.enemyObject.transform.position - owner.transform.position) <= 15)
                    {
                        MoveTurret(owner, owner.enemyObject.transform.position);
                        owner.thisAgent.SetDestination(owner.enemyObject.transform.position);

                        if (Vector3.Distance(owner.transform.position, owner.enemyObject.transform.position) <= owner.attackDistance && owner.canSeeEnemy && timeSinceEnteredState >= timeBeforeAttack) //if the enemy is in attack range and is visible, attack it
                        {
                            owner.botMachine.ChangeState(EnemyAttackState.instance);
                            yield break;
                        }
                    }
                    else
                        RotateBody(owner, owner.enemyObject.transform.position);

                    if (Vector3.Distance(owner.transform.position, owner.enemyObject.transform.position) <= owner.attackDistance && owner.canSeeEnemy && timeSinceEnteredState >= timeBeforeAttack) //if the enemy is in range and visible but the bot is not rotated, just attack it
                    {
                        owner.botMachine.ChangeState(EnemyAttackState.instance);
                        yield break;
                    }
                }
            }
            else
            {
                owner.thisAgent.SetDestination(owner.transform.position);
            }
            yield return null;
        }
    }

    private void RotateBody(EnemyAIMachine _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(EnemyAIMachine _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);
    }
}