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

public class EnemyAIMachine : MonoBehaviour
{
    [HideInInspector]
    public EnemyBotStateMachine botMachine;
    [HideInInspector]
    public GameManager gameMgr;
    [HideInInspector]
    public NavMeshAgent thisAgent;
    [HideInInspector]
    public DisplayLog logD;
    [HideInInspector]
    public LineRenderer laserLine;
    [HideInInspector]
    public Health health;
    [HideInInspector]
    public AudioSource audioS;
    [HideInInspector]
    public Animator animator;
    [HideInInspector]
    public SoundManager soundMgr;

    public string displayName;
    public int searchRadius;
    public int retreatRadius;
    public int reinforcementRadius;
    public int attackDistance;
    public int followDistance;
    public int hitChance;
    public int critChance;
    public int turretRotateSpeed;
    public int barrelMoveSpeed;
    public int bodyRotateSpeed;
    public float fireRate;
    public Transform lineOrigin;
    public Transform barrelEnd;
    public Transform turretPos;
    public Transform barrelPos;
    public Vector3 contactPoint;
    public GameObject partnerBot;
    public GameObject partnerBot1;
    public GameObject objective;
    public GameObject enemyObject;
    public GameObject impactObject;
    public bool disabled = false;
    public bool canSeeEnemy = false;
    public bool onTarget = false;
    public bool leader = false;
    public bool defender = false;
    public bool turretBot = false;
    public bool stateSet = false;
    public bool removingEnemy = false;
    public bool insideNormalSearch = false;
    public bool insideDefend = false;
    public bool insideTurret = false;
    public bool insidePartner = false;
    public ParticleSystem laserParticles;
    public Light barrelLight;
    public List<GameObject> movingBotsOnly = new List<GameObject>();
    public List<GameObject> additionalEnemies = new List<GameObject>();
    public List<GameObject> nearbyFriendlies = new List<GameObject>();
    public List<GameObject> friendlyBots;
    public List<Material> lasers = new List<Material>();

    private float timeToScan = 0;

    private void Awake()
    {
        transform.parent = null;
        foreach (GameObject bot in GameObject.FindGameObjectsWithTag("Enemy"))
        {
            friendlyBots.Add(bot);
        }
        friendlyBots.Remove(this.gameObject);

        botMachine = GetComponent<EnemyBotStateMachine>();

        if (!turretBot)
        {
            thisAgent = GetComponent<NavMeshAgent>();
            displayName = "Enemy Bot";
        }
        else
        {
            thisAgent = null;
            displayName = "Enemy Turret";
        }

        laserLine = GetComponent<LineRenderer>();
        laserLine.enabled = false;
        logD = GameObject.Find("RunningUI/Text Log/Log Panel/Content").GetComponent<DisplayLog>();
        soundMgr = GameObject.Find("Persistent Object").GetComponent<SoundManager>();
        gameMgr = GameObject.Find("Persistent Object").GetComponent<GameManager>();
        audioS = GetComponent<AudioSource>();
        barrelLight = barrelEnd.gameObject.GetComponent<Light>();
        animator = GetComponent<Animator>();
        barrelLight.enabled = false;
    }

    private void Start()
    {
        foreach (GameObject bot in GameObject.FindGameObjectsWithTag("Enemy"))
        {
            if (bot.GetComponent<Health>())
            {
                if (bot.GetComponent<EnemyAIMachine>().turretBot == false)
                    movingBotsOnly.Add(bot);
            }

        }
        movingBotsOnly.Remove(this.gameObject);

        if (gameMgr.missionName == "Hack")
        {
            objective = GameObject.FindGameObjectWithTag("Terminal");
        }
        else if (gameMgr.missionName == "Defend")
        {
            objective = GameObject.FindGameObjectWithTag("DefendStructure");
        }
        else if (gameMgr.missionName == "Assault")
        {
            objective = GameObject.FindGameObjectWithTag("Cap Area");
        }
        else if (gameMgr.missionName == "Destroy")
        {
            objective = GameObject.FindGameObjectWithTag("EnemyStructure");
        }
        else if (gameMgr.missionName == "Protect")
        {
            objective = gameMgr.allyBots[0];
        }
    }

    void Update()
    {
        if (enemyObject != null) //if the enemy object is still set as a target despite being set to inactive, remove it here
            if (enemyObject.activeSelf == false)
                enemyObject = null;


        if (!turretBot)
        {
            timeToScan += Time.deltaTime;

            if (timeToScan >= 1.0f)
            {
                DrawSearchRays();

                DrawBarrelRay();

                timeToScan = 0.0f;
            }
        }
        else
        {
            DrawSearchRays();

            DrawBarrelRay();
        }


        if (!stateSet)
            SetMissionState();
    }

    public void DrawSearchRays() //draw rays out to detect things in the world
    {
        Quaternion startingAngle = Quaternion.AngleAxis(-60, Vector3.up);
        Quaternion stepAngle = Quaternion.AngleAxis(5, Vector3.up);

        RaycastHit hit;
        var angle = transform.rotation * startingAngle;
        var direction = angle * Vector3.forward;

        for (var i = 0; i < 72; i++)
        {
            if (Physics.Raycast(lineOrigin.transform.position, direction, out hit, searchRadius))
            {
                if (hit.collider.gameObject.CompareTag("Target"))
                {
                    Debug.DrawRay(lineOrigin.transform.position, direction * hit.distance, Color.red);
                    canSeeEnemy = true;
                    additionalEnemies.Add(hit.collider.gameObject);
                    additionalEnemies = additionalEnemies.Distinct().ToList();

                    SetTarget();

                    break;
                }
                else if (hit.collider.gameObject.CompareTag("DefendStructure"))
                {
                    Debug.DrawRay(lineOrigin.transform.position, direction * hit.distance, Color.green);
                    canSeeEnemy = true;
                    additionalEnemies.Add(hit.collider.gameObject);
                    additionalEnemies = additionalEnemies.Distinct().ToList();

                    SetTarget();

                    break;
                }
                else if (hit.collider.gameObject.CompareTag("Enemy"))
                {
                    Debug.DrawRay(lineOrigin.transform.position, direction * hit.distance, Color.blue);
                    nearbyFriendlies.Add(hit.collider.gameObject);
                    nearbyFriendlies = nearbyFriendlies.Distinct().ToList();
                }
                else
                {
                    Debug.DrawRay(lineOrigin.transform.position, direction * hit.distance, Color.yellow);
                    canSeeEnemy = false;
                }
            }
            else
            {
                Debug.DrawRay(lineOrigin.transform.position, direction * searchRadius, Color.white);
                canSeeEnemy = false;
            }
            direction = stepAngle * direction;
        }

        for (int i = 0; i < additionalEnemies.Count; i++)
        {
            if (Vector3.Distance(transform.position, additionalEnemies[i].transform.position) > searchRadius || additionalEnemies[i].activeSelf == false)
                additionalEnemies.RemoveAt(i);
        }

        for (int i = 0; i < nearbyFriendlies.Count; i++)
        {
            if (Vector3.Distance(transform.position, nearbyFriendlies[i].transform.position) > searchRadius || nearbyFriendlies[i].activeSelf == false)
                nearbyFriendlies.RemoveAt(i);
        }
    }

    public void DrawBarrelRay() //draw the barrel ray to determine if the barrel is on target
    {
        RaycastHit hit;

        if (Physics.Raycast(barrelEnd.transform.position, barrelEnd.forward, out hit, attackDistance + 10))
        {
            if (hit.collider.gameObject.CompareTag("Target") || hit.collider.gameObject.CompareTag("DefendStructure"))
            {
                Debug.DrawRay(barrelEnd.transform.position, barrelEnd.forward * hit.distance, Color.red);
                contactPoint = hit.point;
                onTarget = true;
            }
            else
            {
                Debug.DrawRay(barrelEnd.transform.position, barrelEnd.forward * hit.distance, Color.yellow);
                onTarget = false;
            }
        }
        else
        {
            Debug.DrawRay(barrelEnd.transform.position, barrelEnd.forward * attackDistance);
            onTarget = false;
        }
    }

    public void SetMissionState() //when the bot is spawned in, have it decide what mode to enter
    {
        if (!stateSet)
        {
            if (gameMgr.missionName == "Defend" || gameMgr.missionName == "Assault" || gameMgr.missionName == "Protect" || gameMgr.missionName == "Destroy" || gameMgr.missionName == "Hack")
            {
                if (defender)
                {
                    botMachine.ChangeState(EnemyMoveToState.instance);
                    insideDefend = true;
                }
                else
                {
                    SetSearch();
                }
            }
            else if (gameMgr.missionName == "Kill")
            {
                SetSearch();
            }

            stateSet = true;
        }
    }

    public void SetTarget() //after enemies are found this method will decide which enemy is the current target
    {
        float minDistance = float.MaxValue;
        GameObject targetBot = null;

        if (additionalEnemies.Count > 0) //if the list is not empty
        {
            for (int i = 0; i < additionalEnemies.Count; i++) //check if any of the enemies in the list are not active before setting the target
            {
                if (additionalEnemies[i].activeSelf == false)
                    additionalEnemies.Remove(additionalEnemies[i]);
            }

            if (additionalEnemies.Count == 1) //if theres only one enemy 
            {
                enemyObject = additionalEnemies[0];
                health = enemyObject.GetComponent<Health>();
            }
            else if (additionalEnemies.Count > 1) //if there is more than 1 enemy
            {
                for (int i = 0; i < additionalEnemies.Count; i++)// for each enemy in the list get the distance between this bot and the enemy and then decide if that distance is the shortest one
                {
                    float thisDistance = Vector3.Distance(transform.position, additionalEnemies[i].transform.position);

                    if (thisDistance < minDistance)
                    {
                        minDistance = thisDistance;
                        targetBot = additionalEnemies[i];
                    }
                }
                //after the loop is complete set the enemyobject to the target that is closest
                enemyObject = targetBot;
                health = enemyObject.GetComponent<Health>();
            }
        }
    }

    public void SetSearch() //called to set the normal search mode when the bot is not performing special actions
    {
        if (movingBotsOnly.Count >= 9)
        {
            if (!turretBot && leader == true)
            {
                botMachine.ChangeState(EnemySearchState.instance);
                insideNormalSearch = true;
            }

            if (!turretBot && leader == false)
            {
                botMachine.ChangeState(EnemyPartnerState.instance);
                insidePartner = true;
            }

            if (turretBot)
            {
                botMachine.ChangeState(EnemyTurretSearchState.instance);
                insideTurret = true;
            }
        }

        if (movingBotsOnly.Count < 9)
        {
            if (!turretBot)
            {
                botMachine.ChangeState(EnemySearchState.instance);
                insideNormalSearch = true;
            }

            if (turretBot)
            {
                botMachine.ChangeState(EnemyTurretSearchState.instance);
                insideTurret = true;
            }
        }
    }

    public void MoveToObjective() //used from other scripts to call enemy bots to an objective
    {
        insideDefend = true;
        insideTurret = false;
        insideNormalSearch = false;
        insidePartner = false;
        botMachine.ChangeState(EnemyMoveToState.instance);
    }

    public void CreateImpactParticles()
    {
        Instantiate(impactObject, contactPoint, Quaternion.identity, gameObject.transform.parent);
    }
}