EnemyAi

PHOTO EMBED

Thu Apr 28 2022 14:10:26 GMT+0000 (Coordinated Universal Time)

Saved by @DanDHenshaw

using UnityEngine;
using UnityEngine.AI;
using Random = UnityEngine.Random;

public class EnemyAi : MonoBehaviour
{
    public NavMeshAgent agent;

    public Transform player;
    
    private AudioSource audioSource;
    private Animator animator;

    public LayerMask whatIsGround, whatIsPlayer;

    public float health = 100f;
    
    [Header("Patrolling")] 
    public Vector3 walkPoint;
    private bool walkPointSet;
    public float walkPointRange;
    [SerializeField] private AudioClip[] footstepSounds;

    [Header("Attacking")] 
    public float timeBetweenAttacks, reloadTime;
    private bool alreadyAttacked;
    public GameObject projectile;
    public float damage;

    [Header("States")] 
    public float sightRange; 
    public float attackRange;
    public bool playerInSightRange, playerInAttackRange;

    public GameObject[] guns;
    public AudioClip[] shootingSounds;
    public AudioClip[] reloadingSounds;
    public AudioClip reloadClip, shotClip;
    public ParticleSystem muzzleFlash;
    public Animator gunAnimator;
    public AudioSource gunAudioSource;
    public Transform spawnPoint;

    public float currentAmmo;
    public float ammo;
    
    private Vector3 lastPosition;
    private float moveMinimum = 0.01f;

    private void Awake()
    {
        player = GameObject.Find("PlayerController").transform;
        agent = GetComponent<NavMeshAgent>();
        audioSource = GetComponent<AudioSource>();
        animator = GetComponent<Animator>();

        int randomGun = Random.Range(0, guns.Length);
        guns[randomGun].SetActive(true);
        gunAnimator = guns[randomGun].GetComponent<Animator>();
        gunAudioSource = guns[randomGun].GetComponent<AudioSource>();
        muzzleFlash = guns[randomGun].GetComponentInChildren<ParticleSystem>();
        spawnPoint = guns[randomGun].transform.Find("AttackPoint");

        reloadClip = reloadingSounds[randomGun];
        shotClip = shootingSounds[randomGun];

        if (randomGun == 0)
        {
            ammo = 6;
            damage = 10;
        } else if (randomGun == 1)
        {
            ammo = 2;
            damage = 20;
        }

        currentAmmo = ammo;
    }

    private void Start()
    {
        GameManager.instance.enemies++;
        GameManager.instance.enemiesSpawned = true;
    }

    private void Update()
    {
        // Check for player in sight and attack range
        playerInSightRange = Physics.CheckSphere(transform.position, sightRange, whatIsPlayer);
        playerInAttackRange = Physics.CheckSphere(transform.position, attackRange, whatIsPlayer);
        
        if(!playerInSightRange && !playerInAttackRange) Patroling();
        if(playerInSightRange && !playerInAttackRange) ChasePlayer();
        if(playerInSightRange && playerInAttackRange) AttackPlayer();
        
        if (IsMoving())
        {
            animator.SetBool("Walking", true);
        }
        else
        {
            animator.SetBool("Walking", false);
        }
        
        lastPosition = transform.position;
    }

    private void Patroling()
    {
        if (!walkPointSet) SearchWalkPoint();

        if (walkPointSet) agent.SetDestination(walkPoint);

        Vector3 distanceToWalkPoint = transform.position - walkPoint;
        
        // Reached walkpoint
        if (distanceToWalkPoint.magnitude < 1f) walkPointSet = false;
    }

    private void SearchWalkPoint()
    {
        // Calculate random point in range
        float randomX = Random.Range(-walkPointRange, walkPointRange);
        float randomZ = Random.Range(-walkPointRange, walkPointRange);

        walkPoint = new Vector3(transform.position.x + randomX, transform.position.y, transform.position.z + randomZ);

        if (Physics.Raycast(walkPoint, -transform.up, 2f, whatIsGround)) walkPointSet = true;
    }

    private void ChasePlayer()
    {
        agent.SetDestination(player.position);
    }

    private void AttackPlayer()
    {
        // Make sure enemy doesn't move
        agent.SetDestination(transform.position);
        transform.LookAt(player);

        if (!alreadyAttacked && currentAmmo > 0)
        {
            // Attack
            GameObject _projectile = Instantiate(projectile, spawnPoint.position, Quaternion.identity);
            _projectile.GetComponent<ProjectileScript>().damage = damage;
            Rigidbody rb = _projectile.GetComponent<Rigidbody>();
            rb.AddForce(transform.forward * 32f, ForceMode.Impulse);
            rb.AddForce(transform.up * 0f, ForceMode.Impulse);
            
            muzzleFlash.Play();
            gunAnimator.SetTrigger("Shot");
            gunAudioSource.clip = shotClip;
            gunAudioSource.Play();

            currentAmmo--;
            alreadyAttacked = true;
            Invoke(nameof(ResetAttack), timeBetweenAttacks);
        } else if (currentAmmo <= 0 && !alreadyAttacked)
        {
            currentAmmo = ammo;
            
            gunAnimator.SetTrigger("Reload");
            gunAudioSource.clip = reloadClip;
            gunAudioSource.Play();
            
            alreadyAttacked = true;
            Invoke(nameof(ResetReload), reloadTime);
        }
    }

    private void ResetAttack()
    {
        alreadyAttacked = false;
    }

    private void ResetReload()
    {
        alreadyAttacked = false;
    }
    
    public void Footstep()
    {
        audioSource.clip = footstepSounds[Random.Range(0, footstepSounds.Length)];
        audioSource.Play();
    }

    public void TakeDamage(float damage)
    {
        health -= damage;

        if (health <= 0)
        {
            Invoke(nameof(DestroyEnemy), 0f);
        }
    }

    private void DestroyEnemy()
    {
        GameManager.instance.enemiesDead++;
        Destroy(gameObject);
    }
    
    bool IsMoving()
    {
        float distance = Vector3.Distance(transform.position, lastPosition);
        return (distance > moveMinimum);
    }

    private void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, attackRange);
        Gizmos.color = Color.yellow;
        Gizmos.DrawWireSphere(transform.position, sightRange);
    }
}
content_copyCOPY