Degulleo3D/Assets/Scripts/Character/Enemy/EnemyController.cs
2025-04-18 13:12:21 +09:00

105 lines
3.0 KiB
C#

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))]
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 float WalkSpeed => walkSpeed;
public float RunSpeed => runSpeed;
[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<EnemyState, IEnemyState> _enemyStates;
private void Awake()
{
EnemyAnimator = GetComponent<Animator>();
Agent = GetComponent<NavMeshAgent>();
}
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, IEnemyState>
{
{ 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)
{
return hitColliders[0].transform;
}
return null;
}
#endregion
}