Projext/Assets/Scripts/Enemy/AI/NormalMonster.cs

98 lines
3.6 KiB
C#
Raw Normal View History

2026-02-02 08:30:23 +00:00
using UnityEngine;
using UnityEngine.AI;
public class NormalMonster : MonsterClass
{
[Header("전투")]
[SerializeField] private float damage = 10f; // ⭐ 이 변수는 OnAttackHit에서 사용됩니다.
[SerializeField] private float attackRange = 2f;
[SerializeField] private float attackDelay = 1.5f;
private float lastAttackTime;
[Header("공격 / 이동 애니메이션")]
[SerializeField] private string[] attackAnimations = { "Monster_Attack_1" };
[SerializeField] private string Monster_Walk = "Monster_Walk";
// ❌ [에러 해결] Monster_Idle 변수가 여기서 삭제되었습니다. (부모인 MonsterClass 것을 사용합니다)
[Header("AI 설정")]
[SerializeField] private float stopBuffer = 0.3f;
[SerializeField] private float patrolRadius = 5f;
[SerializeField] private float patrolInterval = 2f;
private float nextPatrolTime;
private float repathInterval = 0.3f;
private float nextRepathTime;
private int attackIndex;
private bool isPlayerInZone;
protected override void Init()
{
if (agent != null) agent.stoppingDistance = attackRange - 0.4f;
if (animator != null) animator.applyRootMotion = false;
}
protected override void ExecuteAILogic()
{
if (isHit || isAttacking || isResting) return;
float distance = Vector3.Distance(transform.position, playerTransform.position);
if (isPlayerInZone || distance <= attackRange * 2f) HandlePlayerTarget();
else Patrol();
UpdateMovementAnimation();
}
void HandlePlayerTarget()
{
float distance = Vector3.Distance(transform.position, playerTransform.position);
if (distance <= attackRange - stopBuffer) TryAttack();
else if (Time.time >= nextRepathTime)
{
if (agent.isOnNavMesh) agent.SetDestination(playerTransform.position);
nextRepathTime = Time.time + repathInterval;
}
}
void TryAttack()
{
if (Time.time < lastAttackTime + attackDelay) return;
lastAttackTime = Time.time;
string attackName = attackAnimations[attackIndex];
attackIndex = (attackIndex + 1) % attackAnimations.Length;
OnAttackStart();
animator.Play(attackName, 0, 0f);
}
// ⭐ [경고 해결] damage 변수를 여기서 사용하여 사용되지 않는다는 경고를 없앱니다.
public void OnAttackHit()
{
if (playerTransform == null || isHit || isDead) return;
if (playerTransform.TryGetComponent<PlayerHealth>(out var pHealth))
{
pHealth.TakeDamage(damage);
Debug.Log($"[전투] 플레이어에게 {damage} 데미지 부여!");
}
}
void UpdateMovementAnimation()
{
if (isAttacking || isHit || isResting) return;
// ⭐ 부모 클래스의 Monster_Idle을 사용합니다.
if (agent.velocity.magnitude < 0.1f) animator.Play(Monster_Idle);
else animator.Play(Monster_Walk);
}
void Patrol()
{
if (Time.time < nextPatrolTime) return;
Vector3 randomPoint = transform.position + new Vector3(Random.Range(-patrolRadius, patrolRadius), 0, Random.Range(-patrolRadius, patrolRadius));
if (NavMesh.SamplePosition(randomPoint, out NavMeshHit hit, 3f, NavMesh.AllAreas))
if (agent.isOnNavMesh) agent.SetDestination(hit.position);
nextPatrolTime = Time.time + patrolInterval;
}
private void OnTriggerEnter(Collider other) { if (other.CompareTag("Player")) isPlayerInZone = true; }
private void OnTriggerExit(Collider other) { if (other.CompareTag("Player")) isPlayerInZone = false; }
}