Files
Dino_Love_Simulation/Assets/02_Scripts/Story/ch4 scrip/JunpyoCollapseEvent.cs
dldydtn9755-crypto dd4f318a9c 컴퓨터 설정까지
2026-07-28 14:08:45 +09:00

152 lines
4.2 KiB
C#

using System.Collections;
using UnityEngine;
using UnityEngine.Events;
public class JunpyoCollapseEvent : MonoBehaviour
{
[Header("구준표")]
[SerializeField] private Animator junpyoAnimator;
[SerializeField] private string collapseTrigger = "Collapse";
[Header("플레이어 시선")]
[SerializeField] private Transform xrOrigin;
[SerializeField] private Transform playerCamera;
[SerializeField] private Transform lookTarget;
[Tooltip("구준표 쪽으로 화면이 돌아가는 시간")]
[SerializeField] private float lookDuration = 0.4f;
[Tooltip("화면 전환을 시작하고 몇 초 뒤 쓰러질지")]
[SerializeField] private float collapseStartDelay = 0.15f;
[Header("페이드 타이밍")]
[Tooltip("쓰러지기 시작한 뒤 페이드 아웃까지 기다리는 시간")]
[SerializeField] private float fadeDelay = 1.3f;
[Header("쓰러진 뒤 실행")]
[SerializeField] private UnityEvent onCollapseFinished;
private bool hasPlayed;
public void PlayCollapse()
{
if (hasPlayed)
return;
if (junpyoAnimator == null)
{
Debug.LogWarning(
"[JunpyoCollapseEvent] 구준표 Animator가 연결되지 않았습니다."
);
return;
}
if (xrOrigin == null ||
playerCamera == null ||
lookTarget == null)
{
Debug.LogWarning(
"[JunpyoCollapseEvent] 플레이어 시선 설정이 비어 있습니다."
);
return;
}
hasPlayed = true;
StartCoroutine(CollapseRoutine());
}
private IEnumerator CollapseRoutine()
{
// 구준표 방향으로 화면 전환 시작
StartCoroutine(LookAtJunpyoRoutine());
// 화면이 돌아가기 시작한 뒤 잠깐 기다림
yield return new WaitForSeconds(collapseStartDelay);
// 구준표 쓰러지는 애니메이션 실행
junpyoAnimator.ResetTrigger(collapseTrigger);
junpyoAnimator.SetTrigger(collapseTrigger);
// 쓰러지는 모습을 보여준 뒤 페이드 아웃
yield return new WaitForSeconds(fadeDelay);
onCollapseFinished?.Invoke();
}
private IEnumerator LookAtJunpyoRoutine()
{
Vector3 cameraForward = playerCamera.forward;
cameraForward.y = 0f;
Vector3 targetDirection =
lookTarget.position - playerCamera.position;
targetDirection.y = 0f;
if (cameraForward.sqrMagnitude < 0.001f ||
targetDirection.sqrMagnitude < 0.001f)
{
yield break;
}
cameraForward.Normalize();
targetDirection.Normalize();
// 현재 시선에서 구준표까지 필요한 좌우 회전각
float totalAngle = Vector3.SignedAngle(
cameraForward,
targetDirection,
Vector3.up
);
float duration = Mathf.Max(0.01f, lookDuration);
float elapsed = 0f;
float previousAngle = 0f;
while (elapsed < duration)
{
elapsed += Time.deltaTime;
float t = Mathf.Clamp01(elapsed / duration);
// 부드럽게 시작하고 부드럽게 멈춤
float easedT = t * t * (3f - 2f * t);
float currentAngle = totalAngle * easedT;
float frameAngle = currentAngle - previousAngle;
// 카메라 현재 위치를 중심으로 XR Origin 회전
// 플레이어 위치가 옆으로 밀리는 현상을 방지
xrOrigin.RotateAround(
playerCamera.position,
Vector3.up,
frameAngle
);
previousAngle = currentAngle;
yield return null;
}
}
public void ResetCollapse()
{
StopAllCoroutines();
hasPlayed = false;
if (junpyoAnimator != null)
junpyoAnimator.ResetTrigger(collapseTrigger);
}
[ContextMenu("Test Collapse")]
private void TestCollapse()
{
PlayCollapse();
}
[ContextMenu("Reset Collapse")]
private void TestResetCollapse()
{
ResetCollapse();
}
}