/* * author: mark joshwel * date: 30/5/2024 * description: enemy AI based off */ using System; using UnityEngine; using UnityEngine.AI; using Random = UnityEngine.Random; /// /// AI patrolling, chasing and capturing behaviour for the enemy /// public class HerAI : MonoBehaviour { /// /// variable for the nav mesh agent that determines where the enemy can move /// public NavMeshAgent agent; /// /// variable for the player's position /// public Transform player; /// /// variables to distinguish ground and player for sensing /// public LayerMask whatIsGround, whatIsPlayer; /// /// patrolling: variable for the next point for her to walk to /// public Vector3 walkPoint; /// /// patrolling: variable for the range of the walk point /// public float walkPointRange; /// /// capturing: variable for the time range between captures /// public float timeBetweenCaptures; /// /// variable specifying the sight range of the enemy /// public float sightRange; /// /// variable specifying the attack range of the enemy /// public float attackRange; /// /// boolean variable for the player being in sight range /// public bool playerInSightRange; /// /// boolean variable for the player being in attack range /// public bool playerInCaptureRange; /// /// capturing: variable for if the enemy has attempted to capture the player /// private bool _attemptedCapture; /// /// variable to store game manager /// private GameManager _game; /// /// patrolling: variable to determine if the next point is set /// private bool _walkPointSet; /// /// private void Awake() { player = GameObject.Find("PlayerObj").transform; agent = GetComponent(); } /// /// private void Update() { //Check for sight and attack range playerInSightRange = Physics.CheckSphere(transform.position, sightRange, whatIsPlayer); playerInCaptureRange = Physics.CheckSphere(transform.position, attackRange, whatIsPlayer); if (!playerInSightRange && !playerInCaptureRange) Patrolling(); if (playerInSightRange && !playerInCaptureRange) ChasePlayer(); if (playerInCaptureRange && playerInSightRange) CapturePlayer(); } /// /// function to find and store the game manager /// /// generic exception when the object is in an unplayable state private void OnEnable() { // get the game manager _game = GameObject.Find("GameManager").GetComponent(); if (_game == null) throw new Exception("HerAI: could not find GameManager (unreachable?)"); } // /// // /// function to destroy the enemy // /// // private void DestroyEnemy() // { // Destroy(gameObject); // } /// /// function to draw/visualize the sight and attack range of the enemy /// private void OnDrawGizmosSelected() { Gizmos.color = Color.red; Gizmos.DrawWireSphere(transform.position, attackRange); Gizmos.color = Color.yellow; Gizmos.DrawWireSphere(transform.position, sightRange); } /// /// function handling patrolling behaviour /// private void Patrolling() { if (!_walkPointSet) SearchWalkPoint(); else agent.SetDestination(walkPoint); // reached walk point if ((transform.position - walkPoint).magnitude < 1f) _walkPointSet = false; } /// /// function to look for and set the next walk point /// private void SearchWalkPoint() { //Calculate random point in range var randomZ = Random.Range(-walkPointRange, walkPointRange); var randomX = 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; } /// /// function to chase the player /// private void ChasePlayer() { agent.SetDestination(player.position); } /// /// function that captures the player and signals the game manager appropriately /// private void CapturePlayer() { // // don't move the enemy // agent.SetDestination(transform.position); // look at me! transform.LookAt(player); // are we under cooldown? if (_attemptedCapture) return; // signal the game manager to show the 'caught!' menu _game.SetDisplayState(GameManager.DisplayState.ScreenCaughtMenu); // set the cooldown _attemptedCapture = true; Invoke(nameof(ResetCapture), timeBetweenCaptures); } /// /// function to reset the capture cooldown, called by Invoke() /// private void ResetCapture() { _attemptedCapture = false; } }