110 lines
3.8 KiB
C#
110 lines
3.8 KiB
C#
using System.Threading;
|
|
using Unity.VisualScripting;
|
|
using UnityEngine;
|
|
|
|
// ============================================================================
|
|
// HazardSkill
|
|
// ----------------------------------------------------------------------------
|
|
// 보스 특별 스킬의 한 종류 (BossSkill 상속). 스킬 프리팹의 루트에 부착.
|
|
//
|
|
// 시퀀스: 자체 애니메이션 재생 → 선딜 → 피해 판정 ON → 유지 → OFF → 후딜 → 자동 파괴
|
|
//
|
|
// 콜라이더의 "움직임"은 이 프리팹의 자체 Animator/클립이 담당한다 (보스와 무관).
|
|
// 이 스크립트는 타이밍에 맞춰 HazardHitbox들의 피해 판정만 ON/OFF 한다.
|
|
// ============================================================================
|
|
public class HazardSkill : BossSkill
|
|
{
|
|
[Header("HazardSkill")]
|
|
[SerializeField] private Animator _animator; // 이 프리팹의 Animator (콜라이더 이동 담당)
|
|
[SerializeField] private string _downAnimationState = "HazardSkillDown";
|
|
[SerializeField] private string _rightAnimationState = "HazardSkillRight";
|
|
[SerializeField] private float _windup = 0.5f; // 애니 시작 ~ 피해 판정 ON
|
|
[SerializeField] private float _activeDuration = 1.5f; // 피해 판정 유지 시간
|
|
[SerializeField] private float _recovery = 0.6f; // 판정 OFF 후 후딜
|
|
[SerializeField] private GameObject _hazardHitboxOrigin;
|
|
[SerializeField] private int _hitBoxDamage = 15;
|
|
|
|
private SkillSupport support;
|
|
|
|
private void Awake()
|
|
{
|
|
if (_animator == null)
|
|
_animator = GetComponentInChildren<Animator>();
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
support = Object.FindFirstObjectByType<SkillSupport>();
|
|
}
|
|
|
|
protected override async Awaitable RunSkill(CancellationToken token)
|
|
{
|
|
try
|
|
{
|
|
int dirChoice = Random.Range(0,2); //0,1
|
|
|
|
if(dirChoice == 0) // Down 포격
|
|
{
|
|
if (_animator != null && !string.IsNullOrEmpty(_downAnimationState))
|
|
_animator.Play(_downAnimationState);
|
|
}
|
|
else if(dirChoice == 1) //Right 포격
|
|
{
|
|
if (_animator != null && !string.IsNullOrEmpty(_rightAnimationState))
|
|
_animator.Play(_rightAnimationState);
|
|
}
|
|
|
|
PredictHazards(dirChoice);
|
|
|
|
// 선딜
|
|
await Awaitable.WaitForSecondsAsync(_windup, token);
|
|
|
|
FireHazards(dirChoice);
|
|
|
|
// 후딜
|
|
await Awaitable.WaitForSecondsAsync(_recovery, token);
|
|
}
|
|
finally
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
private void PredictHazards(int dirChoice)
|
|
{
|
|
SkillPredict[] predicts = dirChoice switch { 0 => support.DownHazardPredicts, 1=> support.RightHazardPredicts, _=> null};
|
|
|
|
for (int i = 0; i < predicts.Length; i++)
|
|
{
|
|
if(predicts[i] != null)
|
|
predicts[i].PredictVFX.Play();
|
|
}
|
|
}
|
|
|
|
private void FireHazards(int dirChoice)
|
|
{
|
|
Transform[] hazardPoss = dirChoice switch { 0 => support.DownHazardFirePos, 1=> support.RightHazardFirePos, _=> null};
|
|
Vector2 attackDir = dirChoice switch {0 => Vector2.down,1=>Vector2.right,_=>Vector2.left};
|
|
|
|
if (hazardPoss == null) return;
|
|
|
|
for (int i = 0; i < hazardPoss.Length; i++)
|
|
{
|
|
GameObject hitbox = Instantiate(_hazardHitboxOrigin,hazardPoss[i].transform);
|
|
HazardHitbox hazardHitbox = hitbox.GetComponent<HazardHitbox>();
|
|
if(hazardHitbox != null)
|
|
{
|
|
hazardHitbox.Damage = _hitBoxDamage;
|
|
}
|
|
|
|
Rigidbody2D hitbox_rb = hitbox.GetComponent<Rigidbody2D>();
|
|
if(hitbox_rb != null)
|
|
{
|
|
hitbox_rb.AddForce(attackDir*100.0f);
|
|
}
|
|
|
|
Destroy(hitbox,5f);
|
|
}
|
|
}
|
|
}
|