using System; using System.Threading; using UnityEngine; // ============================================================================ // BossSkill // ---------------------------------------------------------------------------- // 보스 "특별 스킬"의 베이스 클래스. 스킬 하나 = 자기완결적 프리팹 하나. // // [스킬 프리팹] = BossSkill(상속) 컴포넌트 + 자체 Animator + HazardHitbox 자식들 // // 동작 흐름: // - BossAI._skillPrefabs에 프리팹을 등록 (씬 인스턴스가 아닌 에셋 참조) // - 시전 시 BossAI가 프리팹을 Instantiate → Begin() 호출 // - 스킬은 시퀀스가 끝나면 스스로 Destroy // - 취소(페이즈 전환·사망)는 BossAI가 인스턴스를 Destroy → 콜라이더도 함께 사라짐 // // MinPhase/Range/Cooldown은 BossAI가 프리팹에서 직접 읽어 사용 가능 여부를 판단. // 쿨다운 "타이머"는 보스별 상태라 BossAI가 추적한다. // // 새 스킬 추가: BossSkill을 상속한 컴포넌트로 프리팹을 만들고 RunSkill만 구현. // ============================================================================ public abstract class BossSkill : MonoBehaviour { [Header("BossSkill")] [SerializeField] private int _minPhase; // 이 페이즈(0부터) 이상에서만 사용 가능 [SerializeField] private float _range = 4f; // 타겟이 이 X거리 안일 때만 사용 [SerializeField] private float _cooldown = 8f; // 재사용 대기 (타이머는 BossAI가 보스별로 추적) [SerializeField] private string _casterAnimationState = "BossCast"; // 시전 중 보스가 재생할 애니메이션 public int MinPhase => _minPhase; public float Range => _range; public float Cooldown => _cooldown; public string CasterAnimationState => _casterAnimationState; // BossAI가 인스턴스를 만든 직후 호출. 시퀀스를 끝까지 실행하고 스스로 파괴한다. // destroyCancellationToken: BossAI가 이 인스턴스를 Destroy하면 시퀀스가 취소된다. public async void Begin() { try { await RunSkill(destroyCancellationToken); } catch (OperationCanceledException) { return; // 외부에서 Destroy됨 → GameObject 이미 파괴 중이므로 그대로 종료 } catch (Exception e) { Debug.LogException(e, this); // 스킬 버그가 나도 아래 Destroy로 정리는 보장 } Destroy(gameObject); } // 서브클래스가 실제 스킬 시퀀스를 구현. token이 취소되면 finally에서 정리할 것. protected abstract Awaitable RunSkill(CancellationToken token); }