using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyAI : MonoBehaviour, IEnemy
{
//Set up Serialized variables
[SerializeField] private float roamChangeDirFloat = 2f;
[SerializeField] private float attackRange = 5f;
[SerializeField] private MonoBehaviour enemyType;
[SerializeField] private float attackCooldown = 2f;
[SerializeField] private bool stopMovingWhileAttacking = false;
//Set up Attacking variable.
private bool canAttack = true;
///
/// This method sets Roaming and Attacking States to be used later on.
///
private enum State{
Roaming,
Attacking
}
//Set up Vector 2 and time variables.
private Vector2 roamPosition;
private float timeRoaming = 0f;
//Set up state and enemypathfinding variables.
private State state;
private EnemyPathfinding enemyPathfinding;
///
/// This method is called when the game first start and it
/// Gets the component for enemyPathfinding ans sets the state
/// to Roaming.
///
private void Awake()
{
enemyPathfinding = GetComponent();
state = State.Roaming;
}
///
/// This method is called when the game first starts just like
/// the Awake method but it is called on the frame when
/// a script is enabled and it gets the roamPosition.
///
private void Start(){
roamPosition = GetRoamingPosition();
}
///
/// This method initializes the MovementStateControl
/// throughout the game runs as the Update method
/// keeps updating.
///
private void Update(){
MovementStateControl();
}
///
/// This method manages the state of your enemy's behavior.
/// It switches between different states (Roaming and Attacking) and
/// calls corresponding methods (Roaming() and Attacking()) based on the current state.
///
private void MovementStateControl(){
//Change State from
switch (state)
{
//Default state - Roaming
default:
case State.Roaming:
Roaming();
break;
//New state - Attacking
case State.Attacking:
Attacking();
break;
}
}
///
/// This method controls how the enemy behaves while it is in the roaming state,
/// managing movement towards a designated roam position, checking proximity to
/// the player for potential attack, and periodically updating the roam position
///
private void Roaming(){
//Update the Roaming time with the delta Time
timeRoaming += Time.deltaTime;
//Move the enemy using pathfinding to the designated roamPosition
enemyPathfinding.MoveTo(roamPosition);
//Check if the Distance of the enemy is less than the attack range of the player
if (Vector2.Distance(transform.position, PlayerController.Instance.transform.position) < attackRange){
//Switch player's state to Attacking so player will attack
state = State.Attacking;
}
//Change the roamPosition after exceeding the roamChangeDirFloat duration.
if (timeRoaming > roamChangeDirFloat){
roamPosition = GetRoamingPosition();
}
}
///
/// The enemy attacks the player.
///
public void Attack()
{
//Enemy Attacks
}
///
/// This method controls how the player will go from attacking mode to roaming mode
/// depending on whether the condition has been met, condition being if the enemy
/// is too far from the player for the player to attack.
///
private void Attacking(){
//Checks if the Distance of the enemy is bigger than the attack range
if (Vector2.Distance(transform.position, PlayerController.Instance.transform.position) > attackRange){
//Switches from Attacking to roaming mode meaning player won't attack
state = State.Roaming;
}
//Checks if the attack range isn't equal to 0 and player can attack
if (attackRange != 0 && canAttack){
//if condition is met player can attack is false
canAttack = false;
//Perform the attack action by casting enemyType to IEnemy and calling the Attack method.
(enemyType as IEnemy).Attack();
//check if the enemy should stop moving while attacking.
if (stopMovingWhileAttacking){
//Stop enemy movement during attack
enemyPathfinding.StopMoving();
} else {
//continue moving to the roam position while attacking
enemyPathfinding.MoveTo(roamPosition);
}
//Start coroutine to handle the cool down between each attack
StartCoroutine(AttackCooldownRoutine());
}
}
///
/// This method handles the routine for the attack cool down
/// called on the method above.
///
///
private IEnumerator AttackCooldownRoutine(){
//Wait for seconds which is the attack cool down time
yield return new WaitForSeconds(attackCooldown);
//After waiting for the attack cool down time, player can attack again
canAttack = true;
}
///
/// This method resets the roaming timer and generates a new random roaming position for the enemy.
///
///
private Vector2 GetRoamingPosition(){
//reset time roaming count to 0
timeRoaming = 0f;
//Generate a new Vector2 with random x and y values between -1 and 1, normalize it to ensure the vector has a magnitude of 1.
//This gives the enemy a new direction to roam in.
return new Vector2(Random.Range(-1f, 1f), Random.Range(-1f, 1f)).normalized;
}
}