using System.Threading; using UnityEngine; public class EarthquakeSkill : BossSkill { [Header("EarthquakeSkill")] [SerializeField] private float _windup = 0.5f; // 애니 시작 ~ 피해 판정 ON [SerializeField] private float _activeDuration = 1.5f; // 피해 판정 유지 시간 [SerializeField] private float _recovery = 0.6f; // 판정 OFF 후 후딜 [SerializeField] private int _damage = 15; [Header("Camera Shake")] [SerializeField] private float _cameraShakeDuration = 0.5f; [SerializeField] private float _cameraShakeStrength = 0.5f; [SerializeField] private float _liftForce = 0.5f; // 지면 피격 시 띄우는 세기 protected override async Awaitable RunSkill(CancellationToken token) { try { // 선딜 await Awaitable.WaitForSecondsAsync(_windup, token); Earthquake(); // 후딜 await Awaitable.WaitForSecondsAsync(_recovery, token); } finally { } } private void Earthquake() { PlayerController player = GameManager.Instance.LocalPlayer; if (player == null) return; ShakeCamera(); // 플레이어가 지면에 닿아 있을 때만 발동. 공중이면 아무 효과 없음. if (!player.IsGrounded) return; // 지면 접촉 중: 살짝 띄우면서 데미지. player.Launch(new Vector2(0f, _liftForce)); player.TakeDamage(_damage); } private async void ShakeCamera() { if (_cameraShakeDuration <= 0f || _cameraShakeStrength <= 0f) return; Camera mainCamera = Camera.main; if (mainCamera == null) return; Transform cameraTransform = mainCamera.transform; Vector3 previousOffset = Vector3.zero; float elapsed = 0f; try { while (elapsed < _cameraShakeDuration) { float fade = 1f - elapsed / _cameraShakeDuration; Vector2 offset = Random.insideUnitCircle * (_cameraShakeStrength * fade); Vector3 currentOffset = new Vector3(offset.x, offset.y, 0f); cameraTransform.localPosition += currentOffset - previousOffset; previousOffset = currentOffset; await Awaitable.NextFrameAsync(destroyCancellationToken); elapsed += Time.deltaTime; } } catch (System.OperationCanceledException) { } finally { if (cameraTransform != null) cameraTransform.localPosition -= previousOffset; } } }