using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public enum EnemyState { None, Idle, Trace, Attack, GetHit, Move, Dead } [RequireComponent(typeof(NavMeshAgent))] [RequireComponent(typeof(Animator))] [RequireComponent(typeof(EnemyAttackController))] public abstract class EnemyController : CharacterBase { [Header("AI")] [SerializeField] private float detectCircleRadius = 10f; // 플레이어 탐지 범위 [SerializeField] private LayerMask targetLayerMask; // 플레이어 레이어 마스크 public NavMeshAgent Agent { get; private set; } public Animator EnemyAnimator { get; private set; } public EnemyState CurrentState {get; private set;} public EnemyAttackController EnemyAttackController { get; private set; } public float WalkSpeed => walkSpeed; public float RunSpeed => runSpeed; public Transform TraceTargetTransform { get; private set; } [SerializeField] private float walkSpeed = 5; [SerializeField] private float runSpeed = 8; // ----- // 상태 변수 private EnemyStateIdle _enemyStateIdle; private EnemyStateTrace _enemyStateTrace; private EnemyStateAttack _enemyStateAttack; private EnemyStateGetHit _enemyStateGetHit; private EnemyStateDead _enemyStateDead; private EnemyStateMove _enemyStateMove; private Dictionary _enemyStates; private void Awake() { EnemyAnimator = GetComponent(); Agent = GetComponent(); EnemyAttackController = GetComponent(); } protected override void Start() { base.Start(); // 상태 객체 생성 _enemyStateIdle = new EnemyStateIdle(); _enemyStateTrace = new EnemyStateTrace(); _enemyStateAttack = new EnemyStateAttack(); _enemyStateGetHit = new EnemyStateGetHit(); _enemyStateDead = new EnemyStateDead(); _enemyStateMove = new EnemyStateMove(); _enemyStates = new Dictionary { { EnemyState.Idle, _enemyStateIdle }, { EnemyState.Trace, _enemyStateTrace }, { EnemyState.Attack, _enemyStateAttack }, { EnemyState.GetHit, _enemyStateGetHit }, { EnemyState.Dead, _enemyStateDead }, { EnemyState.Move, _enemyStateMove} }; SetState(EnemyState.Idle); } private void Update() { if (CurrentState != EnemyState.None) { _enemyStates[CurrentState].Update(); } } public void SetState(EnemyState newState) { if (CurrentState != EnemyState.None) { _enemyStates[CurrentState].Exit(); } CurrentState = newState; _enemyStates[CurrentState].Enter(this); } #region 적 탐지 // 일정 반경에 플레이어가 진입하면 플레이어 소리를 감지했다고 판단 public Transform DetectPlayerInCircle() { var hitColliders = Physics.OverlapSphere(transform.position, detectCircleRadius, targetLayerMask); if (hitColliders.Length > 0) { TraceTargetTransform = hitColliders[0].transform; return TraceTargetTransform; } return null; } #endregion }