diff --git a/Assets/Scripts/Enemy/BossEnemy.cs b/Assets/Scripts/Enemy/BossEnemy.cs index b3540ea4..e4f4003a 100644 --- a/Assets/Scripts/Enemy/BossEnemy.cs +++ b/Assets/Scripts/Enemy/BossEnemy.cs @@ -11,6 +11,7 @@ namespace Colosseum.Enemy /// 보스 캐릭터. 페이즈 시스템과 동적 AI 전환을 지원합니다. /// Unity Behavior 패키지를 사용하여 Behavior Tree 기반 AI를 구현합니다. /// + public class BossEnemy : EnemyBase { [Header("Boss Settings")] @@ -274,13 +275,16 @@ namespace Colosseum.Enemy return; } - base.HandleDeath(); - - // AI 정지 + // AI 완전 중단 (순서 중요: enabled=false를 먼저 호출하여 Update() 차단) if (behaviorAgent != null) { + behaviorAgent.enabled = false; // 가장 먼저: Update() 호출 방지 behaviorAgent.End(); + behaviorAgent.Graph = null; } + behaviorAgent = null; + + base.HandleDeath(); } #region Debug diff --git a/Assets/Scripts/Enemy/EnemyAnimationController.cs b/Assets/Scripts/Enemy/EnemyAnimationController.cs index 0f260111..faa6b803 100644 --- a/Assets/Scripts/Enemy/EnemyAnimationController.cs +++ b/Assets/Scripts/Enemy/EnemyAnimationController.cs @@ -20,6 +20,7 @@ namespace Colosseum.Enemy private Animator animator; private UnityEngine.AI.NavMeshAgent navMeshAgent; + private EnemyBase enemyBase; private float currentSpeed; private float speedVelocity; @@ -27,6 +28,7 @@ namespace Colosseum.Enemy { animator = GetComponent(); navMeshAgent = GetComponent(); + enemyBase = GetComponent(); } public override void OnNetworkSpawn() @@ -49,6 +51,10 @@ namespace Colosseum.Enemy /// private void UpdateAnimationParameters() { + // 사망 상태에서는 애니메이션 파라미터 업데이트 중단 + if (enemyBase != null && enemyBase.IsDead) + return; + if (animator == null || navMeshAgent == null) return; @@ -71,20 +77,29 @@ namespace Colosseum.Enemy /// public void PlayAttack() { - if (IsServer && animator != null) - { - animator.SetTrigger(attackTriggerParam); - } + if (!IsServer || animator == null) + return; + + // 사망 상태에서는 공격 애니메이션 재생하지 않음 + if (enemyBase != null && enemyBase.IsDead) + return; + + animator.SetTrigger(attackTriggerParam); } + /// /// 스킬 애니메이션 트리거 (외부에서 호출) /// public void PlaySkill() { - if (IsServer && animator != null) - { - animator.SetTrigger(skillTriggerParam); - } + if (!IsServer || animator == null) + return; + + // 사망 상태에서는 스킬 애니메이션 재생하지 않음 + if (enemyBase != null && enemyBase.IsDead) + return; + + animator.SetTrigger(skillTriggerParam); } /// @@ -93,10 +108,14 @@ namespace Colosseum.Enemy /// 트리거 파라미터 이름 public void PlayTrigger(string triggerName) { - if (IsServer && animator != null) - { - animator.SetTrigger(triggerName); - } + if (!IsServer || animator == null) + return; + + // 사망 상태에서는 일반 애니메이션 재생하지 않음 + if (enemyBase != null && enemyBase.IsDead) + return; + + animator.SetTrigger(triggerName); } /// diff --git a/Assets/Scripts/Enemy/EnemyBase.cs b/Assets/Scripts/Enemy/EnemyBase.cs index 03b504d3..ae60dec4 100644 --- a/Assets/Scripts/Enemy/EnemyBase.cs +++ b/Assets/Scripts/Enemy/EnemyBase.cs @@ -23,6 +23,8 @@ namespace Colosseum.Enemy [Header("Data")] [SerializeField] protected EnemyData enemyData; + + // 네트워크 동기화 변수 protected NetworkVariable currentHealth = new NetworkVariable(100f); protected NetworkVariable currentMana = new NetworkVariable(50f); @@ -90,16 +92,6 @@ namespace Colosseum.Enemy isDead.Value = false; } - - - - - - - - - - /// /// 대미지 적용 (서버에서 실행) /// @@ -150,6 +142,34 @@ namespace Colosseum.Enemy return actualHeal; } + /// + /// 사망 애니메이션 재생 (모든 클라이언트에서 실행) + /// + [Rpc(SendTo.Everyone)] + private void PlayDeathAnimationRpc() + { + if (animator != null) + { + // EnemyAnimationController 비활성화 (더 이상 애니메이션 제어하지 않음) + var animController = GetComponent(); + if (animController != null) + { + animController.enabled = false; + } + + // 모든 트리거 리셋 + animator.ResetTrigger("Attack"); + animator.ResetTrigger("Skill"); + animator.ResetTrigger("Hit"); + animator.ResetTrigger("Jump"); + animator.ResetTrigger("Land"); + animator.ResetTrigger("Die"); + + // 즉시 Die 상태로 전환 (다른 애니메이션 중단) + animator.Play("Die", 0, 0f); + } + } + /// /// 사망 처리 (서버에서 실행) /// @@ -157,11 +177,16 @@ namespace Colosseum.Enemy { isDead.Value = true; - if (animator != null) + // 실행 중인 스킬 즉시 취소 + var skillController = GetComponent(); + if (skillController != null) { - animator.SetTrigger("Die"); + skillController.CancelSkill(); } + // 모든 클라이언트에서 사망 애니메이션 재생 + PlayDeathAnimationRpc(); + if (navMeshAgent != null) { navMeshAgent.isStopped = true;