134 lines
3.4 KiB
C#
134 lines
3.4 KiB
C#
using System.Collections;
|
|
using UnityEngine;
|
|
|
|
public class PlayerPushToPoint : MonoBehaviour
|
|
{
|
|
[Header("Player")]
|
|
[SerializeField] private Transform xrOrigin;
|
|
[SerializeField] private Transform playerCamera;
|
|
[SerializeField] private CharacterController characterController;
|
|
|
|
[Header("Push Direction")]
|
|
[SerializeField] private Transform pushDirectionPoint;
|
|
|
|
[Header("Push Settings")]
|
|
[SerializeField] private float pushDistance = 0.9f;
|
|
[SerializeField] private float pushDuration = 0.18f;
|
|
|
|
private bool hasPushed;
|
|
private bool isPushing;
|
|
|
|
public void PushPlayerOnce()
|
|
{
|
|
if (hasPushed || isPushing)
|
|
return;
|
|
|
|
if (xrOrigin == null ||
|
|
playerCamera == null ||
|
|
pushDirectionPoint == null)
|
|
{
|
|
Debug.LogWarning(
|
|
"[PlayerPushToPoint] 연결되지 않은 오브젝트가 있습니다."
|
|
);
|
|
return;
|
|
}
|
|
|
|
hasPushed = true;
|
|
StartCoroutine(PushRoutine());
|
|
}
|
|
|
|
private IEnumerator PushRoutine()
|
|
{
|
|
isPushing = true;
|
|
|
|
// 플레이어에서 포인트로 향하는 방향
|
|
Vector3 direction =
|
|
pushDirectionPoint.position - playerCamera.position;
|
|
|
|
// 수평 방향만 사용
|
|
direction.y = 0f;
|
|
|
|
if (direction.sqrMagnitude < 0.001f)
|
|
{
|
|
Debug.LogWarning(
|
|
"[PlayerPushToPoint] 밀기 방향을 계산할 수 없습니다."
|
|
);
|
|
|
|
hasPushed = false;
|
|
isPushing = false;
|
|
yield break;
|
|
}
|
|
|
|
direction.Normalize();
|
|
|
|
Vector3 startPosition = xrOrigin.position;
|
|
Vector3 targetPosition =
|
|
startPosition + direction * pushDistance;
|
|
|
|
// 시작 높이를 그대로 고정
|
|
float fixedY = startPosition.y;
|
|
targetPosition.y = fixedY;
|
|
|
|
bool controllerWasEnabled =
|
|
characterController != null &&
|
|
characterController.enabled;
|
|
|
|
// 밀리는 동안 바닥이나 장애물 때문에 위로 올라가지 않도록 끔
|
|
if (controllerWasEnabled)
|
|
characterController.enabled = false;
|
|
|
|
float duration = Mathf.Max(0.01f, pushDuration);
|
|
float elapsed = 0f;
|
|
|
|
while (elapsed < duration)
|
|
{
|
|
elapsed += Time.deltaTime;
|
|
|
|
float t = Mathf.Clamp01(elapsed / duration);
|
|
float easedT = 1f - Mathf.Pow(1f - t, 3f);
|
|
|
|
Vector3 nextPosition =
|
|
Vector3.Lerp(startPosition, targetPosition, easedT);
|
|
|
|
// 매 프레임 Y값 강제 고정
|
|
nextPosition.y = fixedY;
|
|
xrOrigin.position = nextPosition;
|
|
|
|
yield return null;
|
|
}
|
|
|
|
// 마지막 위치 정확히 고정
|
|
xrOrigin.position = targetPosition;
|
|
|
|
if (controllerWasEnabled)
|
|
characterController.enabled = true;
|
|
|
|
isPushing = false;
|
|
}
|
|
|
|
public void ResetPush()
|
|
{
|
|
StopAllCoroutines();
|
|
|
|
hasPushed = false;
|
|
isPushing = false;
|
|
|
|
if (characterController != null &&
|
|
!characterController.enabled)
|
|
{
|
|
characterController.enabled = true;
|
|
}
|
|
}
|
|
|
|
[ContextMenu("Test Push")]
|
|
private void TestPush()
|
|
{
|
|
PushPlayerOnce();
|
|
}
|
|
|
|
[ContextMenu("Reset Push")]
|
|
private void TestResetPush()
|
|
{
|
|
ResetPush();
|
|
}
|
|
} |