179 lines
4.6 KiB
C#
179 lines
4.6 KiB
C#
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
|
|
public class RaftRiverController : MonoBehaviour
|
|
{
|
|
[Header("Path")]
|
|
[SerializeField] private Transform[] pathPoints;
|
|
|
|
[Header("Steering Input")]
|
|
[SerializeField] private SteeringKeyXR steeringKey;
|
|
|
|
[Tooltip("체크하면 키 움직임과 반대로 뗏목이 좌우 이동합니다.")]
|
|
[SerializeField] private bool reverseControl = true;
|
|
|
|
[Header("Move Speed")]
|
|
[SerializeField] private float forwardSpeed = 5f;
|
|
[SerializeField] private float turnSpeed = 4f;
|
|
|
|
[Header("Side Control")]
|
|
[SerializeField] private float sideMoveSpeed = 10f;
|
|
|
|
[Tooltip("강 중앙선 기준 좌우 이동 가능 범위입니다. 동굴 폭 46이면 14~16 추천.")]
|
|
[SerializeField] private float maxSideOffset = 16f;
|
|
|
|
[Header("Arrival")]
|
|
[SerializeField] private float pointReachDistance = 1.5f;
|
|
|
|
[Header("Events")]
|
|
public UnityEvent onArrived;
|
|
|
|
private int currentPointIndex = 0;
|
|
private float sideOffset = 0f;
|
|
|
|
private Vector3 currentCenterPosition;
|
|
private Vector3 currentForward;
|
|
private Vector3 currentRight;
|
|
|
|
private bool isFinished = false;
|
|
|
|
public bool IsFinished => isFinished;
|
|
|
|
private void Start()
|
|
{
|
|
if (pathPoints == null || pathPoints.Length == 0)
|
|
{
|
|
Debug.LogWarning("[RaftRiverController] Path Points가 비어 있습니다.", this);
|
|
enabled = false;
|
|
return;
|
|
}
|
|
|
|
currentCenterPosition = transform.position;
|
|
|
|
// 첫 목표 지점은 0번이 아니라 1번부터 가는 것이 자연스러울 때가 많음.
|
|
// 단, 0번이 현재 위치와 다르면 그대로 0번부터 이동.
|
|
currentPointIndex = 0;
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (isFinished)
|
|
return;
|
|
|
|
MoveAlongPath();
|
|
HandleSideControl();
|
|
ApplyRaftPositionAndRotation();
|
|
}
|
|
|
|
private void MoveAlongPath()
|
|
{
|
|
if (currentPointIndex >= pathPoints.Length)
|
|
{
|
|
FinishRaftRide();
|
|
return;
|
|
}
|
|
|
|
Transform targetPoint = pathPoints[currentPointIndex];
|
|
|
|
Vector3 toTarget = targetPoint.position - currentCenterPosition;
|
|
toTarget.y = 0f;
|
|
|
|
float distance = toTarget.magnitude;
|
|
|
|
if (distance < pointReachDistance)
|
|
{
|
|
currentPointIndex++;
|
|
|
|
if (currentPointIndex >= pathPoints.Length)
|
|
{
|
|
FinishRaftRide();
|
|
return;
|
|
}
|
|
|
|
targetPoint = pathPoints[currentPointIndex];
|
|
toTarget = targetPoint.position - currentCenterPosition;
|
|
toTarget.y = 0f;
|
|
}
|
|
|
|
if (toTarget.sqrMagnitude < 0.001f)
|
|
return;
|
|
|
|
currentForward = toTarget.normalized;
|
|
currentCenterPosition += currentForward * forwardSpeed * Time.deltaTime;
|
|
|
|
// 진행 방향 기준 오른쪽 벡터
|
|
currentRight = Vector3.Cross(Vector3.up, currentForward).normalized;
|
|
}
|
|
|
|
private void HandleSideControl()
|
|
{
|
|
float input = 0f;
|
|
|
|
if (steeringKey != null)
|
|
{
|
|
input = steeringKey.SteeringValue;
|
|
}
|
|
else
|
|
{
|
|
// 키 연결 전 테스트용
|
|
input = Input.GetAxis("Horizontal");
|
|
}
|
|
|
|
// 반전은 여기서만 처리
|
|
if (reverseControl)
|
|
{
|
|
input *= -1f;
|
|
}
|
|
|
|
sideOffset += input * sideMoveSpeed * Time.deltaTime;
|
|
sideOffset = Mathf.Clamp(sideOffset, -maxSideOffset, maxSideOffset);
|
|
}
|
|
|
|
private void ApplyRaftPositionAndRotation()
|
|
{
|
|
Vector3 finalPosition = currentCenterPosition + currentRight * sideOffset;
|
|
|
|
// 현재 뗏목 높이 유지
|
|
finalPosition.y = transform.position.y;
|
|
|
|
transform.position = finalPosition;
|
|
|
|
if (currentForward != Vector3.zero)
|
|
{
|
|
Quaternion targetRotation = Quaternion.LookRotation(currentForward, Vector3.up);
|
|
|
|
transform.rotation = Quaternion.Slerp(
|
|
transform.rotation,
|
|
targetRotation,
|
|
turnSpeed * Time.deltaTime
|
|
);
|
|
}
|
|
}
|
|
|
|
private void FinishRaftRide()
|
|
{
|
|
if (isFinished)
|
|
return;
|
|
|
|
isFinished = true;
|
|
|
|
Debug.Log("[RaftRiverController] 목적지 도착. 뗏목 정지.");
|
|
|
|
onArrived?.Invoke();
|
|
}
|
|
|
|
public void StopRaft()
|
|
{
|
|
isFinished = true;
|
|
}
|
|
|
|
public void ResumeRaft()
|
|
{
|
|
isFinished = false;
|
|
}
|
|
|
|
public void SetSteeringKey(SteeringKeyXR newSteeringKey)
|
|
{
|
|
steeringKey = newSteeringKey;
|
|
}
|
|
} |