2026-01-29 16:11:10 +00:00
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using Cinemachine;
|
2026-01-30 06:30:27 +00:00
|
|
|
|
using System.Collections;
|
2026-01-29 16:11:10 +00:00
|
|
|
|
|
|
|
|
|
|
public class CinemachineShake : MonoBehaviour
|
|
|
|
|
|
{
|
|
|
|
|
|
public static CinemachineShake Instance { get; private set; }
|
2026-01-30 06:30:27 +00:00
|
|
|
|
|
|
|
|
|
|
[Header("--- 컴포넌트 연결 ---")]
|
2026-01-29 16:11:10 +00:00
|
|
|
|
private CinemachineImpulseSource _impulseSource;
|
2026-01-30 06:30:27 +00:00
|
|
|
|
[SerializeField] private CinemachineVirtualCamera _vCam;
|
|
|
|
|
|
|
|
|
|
|
|
[Header("--- 줌 설정 ---")]
|
|
|
|
|
|
[SerializeField] private float defaultFOV = 60f;
|
|
|
|
|
|
[SerializeField] private float zoomedFOV = 45f;
|
|
|
|
|
|
[SerializeField] private float zoomSpeed = 5f;
|
|
|
|
|
|
|
|
|
|
|
|
private Coroutine _zoomCoroutine;
|
2026-01-29 16:11:10 +00:00
|
|
|
|
|
|
|
|
|
|
private void Awake()
|
|
|
|
|
|
{
|
|
|
|
|
|
Instance = this;
|
|
|
|
|
|
_impulseSource = GetComponent<CinemachineImpulseSource>();
|
2026-01-30 06:30:27 +00:00
|
|
|
|
if (_vCam == null) _vCam = GetComponent<CinemachineVirtualCamera>();
|
2026-01-29 16:11:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-30 07:45:11 +00:00
|
|
|
|
// ⭐ 렉 없는 타격감: 시간을 0.1배속으로 늘림 (Hit-Slow)
|
|
|
|
|
|
public void HitSlow(float duration = 0.15f, float timeScale = 0.1f)
|
|
|
|
|
|
{
|
|
|
|
|
|
StartCoroutine(DoHitSlow(duration, timeScale));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private IEnumerator DoHitSlow(float duration, float timeScale)
|
|
|
|
|
|
{
|
|
|
|
|
|
Time.timeScale = timeScale; // 멈추지 않고 아주 느리게
|
|
|
|
|
|
yield return new WaitForSecondsRealtime(duration);
|
|
|
|
|
|
Time.timeScale = 1.0f;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ⭐ 카메라 킥: 순간적으로 FOV를 확 줄여 충격을 줌
|
|
|
|
|
|
public void CameraKick(float kickAmount = 8f)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_vCam == null) return;
|
|
|
|
|
|
_vCam.m_Lens.FieldOfView -= kickAmount; // 순간 줌인
|
|
|
|
|
|
SetZoom(false); // AnimateZoom을 통해 부드럽게 복구
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-30 06:30:27 +00:00
|
|
|
|
public void ShakeAttack()
|
2026-01-29 16:11:10 +00:00
|
|
|
|
{
|
|
|
|
|
|
if (_impulseSource == null) return;
|
2026-01-30 07:45:11 +00:00
|
|
|
|
_impulseSource.GenerateImpulse(Vector3.down * 1.5f);
|
2026-01-30 06:30:27 +00:00
|
|
|
|
}
|
2026-01-29 16:11:10 +00:00
|
|
|
|
|
2026-01-30 06:30:27 +00:00
|
|
|
|
public void ShakeNoNo()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_impulseSource == null) return;
|
|
|
|
|
|
_impulseSource.GenerateImpulse(Vector3.right * 0.4f);
|
2026-01-29 16:11:10 +00:00
|
|
|
|
}
|
2026-01-30 06:30:27 +00:00
|
|
|
|
|
|
|
|
|
|
public void SetZoom(bool isZooming)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_vCam == null) return;
|
|
|
|
|
|
if (_zoomCoroutine != null) StopCoroutine(_zoomCoroutine);
|
|
|
|
|
|
float targetFOV = isZooming ? zoomedFOV : defaultFOV;
|
|
|
|
|
|
_zoomCoroutine = StartCoroutine(AnimateZoom(targetFOV));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private IEnumerator AnimateZoom(float target)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_vCam == null) yield break;
|
|
|
|
|
|
while (Mathf.Abs(_vCam.m_Lens.FieldOfView - target) > 0.1f)
|
|
|
|
|
|
{
|
|
|
|
|
|
_vCam.m_Lens.FieldOfView = Mathf.Lerp(_vCam.m_Lens.FieldOfView, target, Time.deltaTime * zoomSpeed);
|
|
|
|
|
|
yield return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
_vCam.m_Lens.FieldOfView = target;
|
|
|
|
|
|
}
|
2026-01-29 16:11:10 +00:00
|
|
|
|
}
|