81 lines
3.0 KiB
C#
81 lines
3.0 KiB
C#
using System;
|
|
using UnityEngine;
|
|
|
|
// ============================================================================
|
|
// Boss
|
|
// ----------------------------------------------------------------------------
|
|
// 보스의 페이즈를 관리하는 컴포넌트. 같은 GameObject의 Enemy(몸)·BossAI(두뇌)와
|
|
// 함께 동작한다.
|
|
// - Health 비율이 임계값 아래로 떨어지면 페이즈 전환
|
|
// - 전환 중엔 Enemy.SetInvulnerable(true)로 무적 + 전환 애니메이션 재생
|
|
// - CurrentPhase를 BossAI가 읽어 공격 패턴을 바꾼다 (BossAttack.MinPhase)
|
|
// ============================================================================
|
|
[RequireComponent(typeof(Enemy))]
|
|
[RequireComponent(typeof(Health))]
|
|
public class Boss : MonoBehaviour
|
|
{
|
|
[Header("Phase")]
|
|
// 페이즈 업이 일어나는 HP 비율 (내림차순). 예: {0.66, 0.33} → 페이즈 0→1→2.
|
|
[SerializeField] private float[] _phaseThresholds = { 0.66f, 0.33f };
|
|
[SerializeField] private string _phaseTransitionAnimation = "BossPhaseChange";
|
|
[SerializeField] private float _phaseTransitionDuration = 1.2f; // 전환(무적) 지속 시간
|
|
|
|
private Enemy _enemy;
|
|
private Health _health;
|
|
private Animator _anim;
|
|
|
|
private int _currentPhase; // 0부터 시작
|
|
private bool _isTransitioning; // 페이즈 전환 진행 중
|
|
|
|
public int CurrentPhase => _currentPhase;
|
|
public bool IsTransitioning => _isTransitioning;
|
|
public event Action<int> OnPhaseChanged; // 전환 완료 시 발화 (인자 = 새 페이즈)
|
|
|
|
private void Awake()
|
|
{
|
|
_enemy = GetComponent<Enemy>();
|
|
_health = GetComponent<Health>();
|
|
_anim = GetComponentInChildren<Animator>();
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (_isTransitioning || _health.IsDead) return;
|
|
if (_currentPhase >= _phaseThresholds.Length) return; // 이미 마지막 페이즈
|
|
|
|
// 현재 페이즈의 임계값 아래로 HP가 떨어지면 다음 페이즈로 전환.
|
|
if (_health.Ratio <= _phaseThresholds[_currentPhase])
|
|
RunPhaseTransition();
|
|
}
|
|
|
|
// 페이즈 전환: 무적 ON → 전환 애니메이션 → 일정 시간 후 무적 OFF + 페이즈 증가.
|
|
// 코루틴 대신 Awaitable 사용. destroyCancellationToken으로 파괴 시 자동 취소.
|
|
private async void RunPhaseTransition()
|
|
{
|
|
_isTransitioning = true;
|
|
_enemy.SetInvulnerable(true);
|
|
|
|
if (_anim != null && !string.IsNullOrEmpty(_phaseTransitionAnimation))
|
|
_anim.Play(_phaseTransitionAnimation);
|
|
|
|
try
|
|
{
|
|
await Awaitable.WaitForSecondsAsync(_phaseTransitionDuration, destroyCancellationToken);
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
return; // 보스가 파괴됨 → 그대로 종료
|
|
}
|
|
|
|
_currentPhase++;
|
|
_enemy.SetInvulnerable(false);
|
|
_isTransitioning = false;
|
|
OnPhaseChanged?.Invoke(_currentPhase);
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
GameManager.Instance.WaveM.GameClear();
|
|
}
|
|
}
|