육지도착

This commit is contained in:
2026-06-22 16:58:32 +09:00
parent f7a71e11d6
commit 74afff5be8
23 changed files with 1500 additions and 54 deletions

View File

@@ -0,0 +1,238 @@
using System.Collections;
using UnityEngine;
public class RaftStartManager : MonoBehaviour
{
private enum StartState
{
Ready,
WaitingForKeyGrab,
Starting,
Riding,
Arrived,
Failed
}
[Header("References")]
[SerializeField] private RaftRiverController raftController;
[SerializeField] private SteeringKeyXR steeringKey;
[Tooltip("현재는 캡슐 요정. 나중에 요정 캐릭터 모델로 교체할 부모 오브젝트를 넣으면 됩니다.")]
[SerializeField] private GameObject fairyObject;
[Header("Obstacles")]
[Tooltip("뗏목 출발 시 함께 작동할 코뿔소들입니다.")]
[SerializeField] private RhinoObstacle[] rhinos;
[Header("Health")]
[SerializeField] private RaftHealth raftHealth;
[Header("Start Settings")]
[SerializeField] private bool waitForKeyGrab = true;
[Tooltip("키를 잡은 뒤 뗏목이 완전히 출발 속도에 도달하기까지 걸리는 시간")]
[SerializeField] private float startAccelerationDuration = 2.0f;
[Tooltip("출발 직후 바로 요정이 사라질지 여부")]
[SerializeField] private bool hideFairyOnStart = true;
[Header("Debug")]
[SerializeField] private bool showDebugLog = true;
private StartState state = StartState.Ready;
private Coroutine startRoutine;
private void Start()
{
SetupStartState();
}
private void Update()
{
if (state != StartState.WaitingForKeyGrab)
return;
if (!waitForKeyGrab)
return;
if (steeringKey != null && steeringKey.IsGrabbed)
{
BeginRaftRide();
}
}
private void SetupStartState()
{
ResolveReferences();
state = StartState.WaitingForKeyGrab;
if (raftController != null)
{
raftController.StopRaft();
raftController.SetSpeedMultiplier(0f);
}
if (raftHealth != null)
{
raftHealth.ResetHealth();
}
StopAllRhinos();
if (fairyObject != null)
{
fairyObject.SetActive(true);
}
if (showDebugLog)
{
Debug.Log("[RaftStartManager] 시작 준비 완료. 키를 잡으면 뗏목이 출발합니다.");
}
}
private void ResolveReferences()
{
if (raftController == null)
raftController = FindFirstObjectByType<RaftRiverController>();
if (steeringKey == null)
steeringKey = FindFirstObjectByType<SteeringKeyXR>();
if (raftHealth == null)
raftHealth = FindFirstObjectByType<RaftHealth>();
if (rhinos == null || rhinos.Length == 0)
rhinos = FindObjectsByType<RhinoObstacle>(FindObjectsSortMode.None);
}
public void BeginRaftRide()
{
if (state == StartState.Starting || state == StartState.Riding)
return;
state = StartState.Starting;
if (hideFairyOnStart && fairyObject != null)
{
fairyObject.SetActive(false);
}
if (startRoutine != null)
StopCoroutine(startRoutine);
startRoutine = StartCoroutine(StartRaftSmoothly());
}
private IEnumerator StartRaftSmoothly()
{
if (raftController == null)
{
Debug.LogWarning("[RaftStartManager] RaftRiverController가 연결되지 않았습니다.", this);
yield break;
}
raftController.SetSpeedMultiplier(0f);
raftController.ResumeRaft();
StartAllRhinos();
if (showDebugLog)
{
Debug.Log("[RaftStartManager] 뗏목 출발 시작. 코뿔소 장애물도 시작합니다.");
}
float timer = 0f;
float duration = Mathf.Max(0.01f, startAccelerationDuration);
while (timer < duration)
{
timer += Time.deltaTime;
float t = Mathf.Clamp01(timer / duration);
float smoothT = t * t * (3f - 2f * t);
raftController.SetSpeedMultiplier(smoothT);
yield return null;
}
raftController.SetSpeedMultiplier(1f);
state = StartState.Riding;
if (showDebugLog)
{
Debug.Log("[RaftStartManager] 뗏목 정상 운항 속도 도달.");
}
}
public void OnRaftArrived()
{
if (state == StartState.Arrived)
return;
state = StartState.Arrived;
if (raftController != null)
{
raftController.SetSpeedMultiplier(0f);
}
StopAllRhinos();
if (showDebugLog)
{
Debug.Log("[RaftStartManager] 목적지 도착. 뗏목 구간 종료. 코뿔소 장애물 정지.");
}
}
public void OnRaftFailed()
{
if (state == StartState.Failed)
return;
state = StartState.Failed;
if (raftController != null)
{
raftController.StopRaft();
raftController.SetSpeedMultiplier(0f);
}
StopAllRhinos();
if (showDebugLog)
{
Debug.Log("[RaftStartManager] 체력 0. 뗏목 구간 실패. 코뿔소 장애물 정지.");
}
}
private void StartAllRhinos()
{
if (rhinos == null)
return;
foreach (RhinoObstacle rhino in rhinos)
{
if (rhino == null)
continue;
rhino.StartRhino();
}
}
private void StopAllRhinos()
{
if (rhinos == null)
return;
foreach (RhinoObstacle rhino in rhinos)
{
if (rhino == null)
continue;
rhino.StopRhino();
}
}
}