Files
Colosseum/Assets/Scripts/Enemy/EnemyAnimationController.cs
dal4segno 5238b65dc2 feat: 적 사망 처리 시스템 개선
- EnemyBase: PlayDeathAnimationRpc로 모든 클라이언트에 사망 애니메이션 동기화
- EnemyAnimationController: 사망 상태에서 애니메이션 업데이트 및 트리거 중단
- BossEnemy: HandleDeath에서 AI 정지 순서 개선 (enabled=false 먼저)

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-03-16 09:46:56 +09:00

127 lines
3.8 KiB
C#

using UnityEngine;
using Unity.Netcode;
namespace Colosseum.Enemy
{
/// <summary>
/// 적 캐릭터 애니메이션 컨트롤러
/// NavMeshAgent 속도에 따라 Idle/Move 애니메이션 제어
/// </summary>
public class EnemyAnimationController : NetworkBehaviour
{
[Header("Animation Parameters")]
[SerializeField] private string speedParam = "Speed";
[SerializeField] private string attackTriggerParam = "Attack";
[SerializeField] private string skillTriggerParam = "Skill";
[Header("Settings")]
[SerializeField] private float speedSmoothTime = 0.1f;
[SerializeField] private float stopThreshold = 0.05f;
private Animator animator;
private UnityEngine.AI.NavMeshAgent navMeshAgent;
private EnemyBase enemyBase;
private float currentSpeed;
private float speedVelocity;
private void Awake()
{
animator = GetComponent<Animator>();
navMeshAgent = GetComponent<UnityEngine.AI.NavMeshAgent>();
enemyBase = GetComponent<EnemyBase>();
}
public override void OnNetworkSpawn()
{
if (!IsServer)
{
enabled = false;
}
}
private void Update()
{
if (!IsServer) return;
UpdateAnimationParameters();
}
/// <summary>
/// 애니메이션 파라미터 업데이트
/// </summary>
private void UpdateAnimationParameters()
{
// 사망 상태에서는 애니메이션 파라미터 업데이트 중단
if (enemyBase != null && enemyBase.IsDead)
return;
if (animator == null || navMeshAgent == null)
return;
// NavMeshAgent의 속도를 기반으로 타겟 속도 계산
float targetSpeed = navMeshAgent.velocity.magnitude;
// 정지 임계값 처리
if (targetSpeed < stopThreshold)
targetSpeed = 0f;
// 부드러운 속도 변화
currentSpeed = Mathf.SmoothDamp(currentSpeed, targetSpeed, ref speedVelocity, speedSmoothTime);
// 애니메이터 파라미터 설정
animator.SetFloat(speedParam, currentSpeed);
}
/// <summary>
/// 공격 애니메이션 트리거 (외부에서 호출)
/// </summary>
public void PlayAttack()
{
if (!IsServer || animator == null)
return;
// 사망 상태에서는 공격 애니메이션 재생하지 않음
if (enemyBase != null && enemyBase.IsDead)
return;
animator.SetTrigger(attackTriggerParam);
}
/// <summary>
/// 스킬 애니메이션 트리거 (외부에서 호출)
/// </summary>
public void PlaySkill()
{
if (!IsServer || animator == null)
return;
// 사망 상태에서는 스킬 애니메이션 재생하지 않음
if (enemyBase != null && enemyBase.IsDead)
return;
animator.SetTrigger(skillTriggerParam);
}
/// <summary>
/// 특정 애니메이션 트리거 재생
/// </summary>
/// <param name="triggerName">트리거 파라미터 이름</param>
public void PlayTrigger(string triggerName)
{
if (!IsServer || animator == null)
return;
// 사망 상태에서는 일반 애니메이션 재생하지 않음
if (enemyBase != null && enemyBase.IsDead)
return;
animator.SetTrigger(triggerName);
}
/// <summary>
/// 현재 애니메이션 속도
/// </summary>
public float CurrentSpeed => currentSpeed;
}
}