using System.Collections; using System.Collections.Generic; using UnityEngine; public class EnemyAI : MonoBehaviour { [SerializeField] private float roamChangeDirFloat = 2f; // Time interval to change roaming direction [SerializeField] private float attackRange = 0f; // Range within which the enemy attacks the player [SerializeField] private MonoBehaviour enemyType; // Reference to the enemy's type (e.g., Sword, Bow) [SerializeField] private float attackCooldown = 2f; // Cooldown time between attacks [SerializeField] private bool stopMovingWhileAttacking = false; // Whether to stop moving while attacking private bool canAttack = true; // Flag to determine if the enemy can attack private enum State { Roaming, // State when the enemy is roaming Attacking // State when the enemy is attacking } private Vector2 roamPosition; // Current position to roam towards private float timeRoaming = 0f; // Time spent in the roaming state private State state; // Current state of the enemy AI private EnemyPathfinding enemyPathfinding; // Reference to the enemy's pathfinding component private void Awake() { enemyPathfinding = GetComponent(); // Get the EnemyPathfinding component on Awake state = State.Roaming; // Start in the Roaming state } private void Start() { roamPosition = GetRoamingPosition(); // Initialize the first roaming position } private void Update() { MovementStateControl(); // Control the movement based on the current state } private void MovementStateControl() { switch (state) { case State.Roaming: Roaming(); // If Roaming, call the Roaming method break; case State.Attacking: Attacking(); // If Attacking, call the Attacking method break; default: break; } } private void Roaming() { timeRoaming += Time.deltaTime; // Increment time spent in Roaming state enemyPathfinding.MoveTo(roamPosition); // Move towards the roam position // Transition to Attacking state if player is within attack range if (Vector2.Distance(transform.position, PlayerController.Instance.transform.position) < attackRange) { state = State.Attacking; } // Change roaming direction after a certain time interval if (timeRoaming > roamChangeDirFloat) { roamPosition = GetRoamingPosition(); } } private void Attacking() { // Transition back to Roaming state if player moves out of attack range if (Vector2.Distance(transform.position, PlayerController.Instance.transform.position) > attackRange) { state = State.Roaming; } // Perform attack if attack range is non-zero and canAttack flag is true if (attackRange != 0 && canAttack) { canAttack = false; (enemyType as IEnemy).Attack(); // Call the Attack method on the enemyType (must implement IEnemy) // Stop moving if stopMovingWhileAttacking is true, otherwise continue moving towards roam position if (stopMovingWhileAttacking) { enemyPathfinding.StopMoving(); } else { enemyPathfinding.MoveTo(roamPosition); } StartCoroutine(AttackCooldownRoutine()); // Start attack cooldown routine } } private IEnumerator AttackCooldownRoutine() { yield return new WaitForSeconds(attackCooldown); // Wait for attack cooldown duration canAttack = true; // Allow the enemy to attack again } private Vector2 GetRoamingPosition() { timeRoaming = 0f; // Reset timeRoaming return new Vector2(Random.Range(-1f, 1f), Random.Range(-1f, 1f)).normalized; // Return a normalized random vector } }