Projext/Assets/7.Other Code/NormalMonster.cs
20071106bjs d50e6f7a7d 프로젝트 수정
UI크기, 배치, 이미지, 카드 능력치에 +-붙는 문제 해결
2026-01-30 11:46:55 +09:00

166 lines
4.8 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using System;
public class NormalMonster : MonsterClass
{
[Header("전투")]
[SerializeField] private float damage = 10f;
[SerializeField] private float attackRange = 2f;
[SerializeField] private float attackDelay = 1.5f;
[SerializeField] private float postAttackDelay = 1.5f;
private float lastAttackTime;
// ⭐ MonsterClass에 OnHealthChanged가 있으므로 여기서는 삭제합니다.
[Header("공격 애니메이션")]
[SerializeField] private string[] attackAnimations = { "Monster_Attack_1" };
[Header("이동 애니메이션")]
[SerializeField] private string Monster_Idle = "Monster_Idle";
[SerializeField] private string Monster_Walk = "Monster_Walk";
[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 Transform player;
private int attackIndex;
private bool isAttacking;
private bool isPlayerInZone;
protected override void Start()
{
base.Start();
player = GameObject.FindWithTag("Player")?.transform;
agent.stoppingDistance = attackRange - 0.4f;
animator.applyRootMotion = false;
}
protected override void Update()
{
if (isDead || player == null) return;
// ⭐ CS0103 에러 해결: 아래 정의된 Patrol()을 호출
if (isPlayerInZone) HandlePlayerTarget();
else Patrol();
// ⭐ CS0103 에러 해결: 아래 정의된 UpdateMovementAnimation()을 호출
UpdateMovementAnimation();
}
void HandlePlayerTarget()
{
float distance = Vector3.Distance(transform.position, player.position);
if (distance <= agent.stoppingDistance + 0.05f)
{
agent.isStopped = true;
agent.velocity = Vector3.zero;
}
else if (!isAttacking)
{
agent.isStopped = false;
}
if (distance <= attackRange - stopBuffer)
{
if (!isAttacking) TryAttack();
}
else if (Time.time >= nextRepathTime && !isAttacking)
{
agent.SetDestination(player.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;
isAttacking = true;
agent.isStopped = true;
agent.velocity = Vector3.zero;
animator.Play(attackName, 0, 0f);
}
// ⭐ CS0506 해결: 부모의 virtual 메서드를 정상적으로 재정의
public override void TakeDamage(float amount)
{
base.TakeDamage(amount); // 부모의 OnDamaged(UI 신호 포함)를 실행
}
public void OnAttackEnd()
{
StartCoroutine(PostAttackWait());
}
private IEnumerator PostAttackWait()
{
yield return new WaitForSeconds(postAttackDelay);
isAttacking = false;
if (agent && agent.isOnNavMesh) agent.isStopped = false;
}
public void OnAttackHit()
{
if (player == null) return;
PlayerHealth playerHealth = player.GetComponent<PlayerHealth>();
if (playerHealth != null) playerHealth.TakeDamage(damage);
}
// ⭐ 복구된 이동 애니메이션 함수
void UpdateMovementAnimation()
{
if (isAttacking || isHit) return;
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(UnityEngine.Random.Range(-patrolRadius, patrolRadius), 0,
UnityEngine.Random.Range(-patrolRadius, patrolRadius));
if (NavMesh.SamplePosition(randomPoint, out NavMeshHit hit, 3f, NavMesh.AllAreas))
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;
}
protected override void StartHit()
{
isAttacking = false;
if (agent && agent.isOnNavMesh) agent.isStopped = false;
base.StartHit();
}
}