Degulleo3D/Assets/Scripts/Character/Enemy/EnemyController.cs
fiore 9c03bfd00a DEG-41 DEG-93 공격 패턴 및 애니메이션 조정
- 부채꼴 가로 베기
- 직선 횡 베기
- 근접 원형 공격
- 원거리 폭탄
2025-04-24 10:40:40 +09:00

146 lines
3.9 KiB
C#

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public enum EnemyState { None, Idle, Trace, Attack, Dead }
[RequireComponent(typeof(NavMeshAgent))]
[RequireComponent(typeof(Animator))]
public abstract class EnemyController : CharacterBase
{
[Header("AI")]
[SerializeField] private float detectCircleRadius = 10f; // 플레이어 탐지 범위
[SerializeField] private LayerMask targetLayerMask; // 플레이어 레이어 마스크
public Transform TraceTargetTransform { get; private set; }
public NavMeshAgent Agent { get; private set; }
public Animator EnemyAnimator { get; private set; }
public EnemyState CurrentState {get; private set;}
public LayerMask TargetLayerMask => targetLayerMask;
public float MoveSpeed => moveSpeed;
public bool IsMeleeCombat { get; protected set; }
// -----
// 애니메이션 관련
private int _currentAnimationTrigger = -1;
// 애니메이션 파라미터 해시값
public static readonly int Idle = Animator.StringToHash("Idle");
public static readonly int Dead = Animator.StringToHash("Dead");
public static readonly int Trace = Animator.StringToHash("Trace");
// -----
// 상태 변수
private EnemyStateIdle _enemyStateIdle;
private EnemyStateTrace _enemyStateTrace;
private EnemyStateAttack _enemyStateAttack;
private EnemyStateDead _enemyStateDead;
private Dictionary<EnemyState, IEnemyState> _enemyStates;
protected virtual void Awake()
{
EnemyAnimator = GetComponent<Animator>();
Agent = GetComponent<NavMeshAgent>();
}
protected override void Start()
{
base.Start();
// 상태 객체 생성
_enemyStateIdle = new EnemyStateIdle();
_enemyStateTrace = new EnemyStateTrace();
_enemyStateAttack = new EnemyStateAttack();
_enemyStateDead = new EnemyStateDead();
_enemyStates = new Dictionary<EnemyState, IEnemyState>
{
{ EnemyState.Idle, _enemyStateIdle },
{ EnemyState.Trace, _enemyStateTrace },
{ EnemyState.Attack, _enemyStateAttack },
{ EnemyState.Dead, _enemyStateDead },
};
SetState(EnemyState.Idle);
}
protected virtual 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);
}
public override void Die()
{
base.Die();
// TODO : 사망 후 동작
}
#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
#region
// Trigger
public void SetAnimation(int hashName)
{
if (_currentAnimationTrigger != -1)
{
EnemyAnimator.ResetTrigger(_currentAnimationTrigger);
}
EnemyAnimator.SetTrigger(hashName);
_currentAnimationTrigger = hashName;
}
// Bool
public void SetAnimation(int hashName, bool value)
{
EnemyAnimator.SetBool(hashName, value);
}
// Float
public void SetAnimation(int hashName, float value)
{
EnemyAnimator.SetFloat(hashName, value);
}
// Integer
public void SetAnimation(int hashName, int value)
{
EnemyAnimator.SetInteger(hashName, value);
}
#endregion
}