Files
WhaleAdventure_VR/Assets/02_Scripts/Blackjack/PlayerChairSeat.cs
2026-06-19 15:24:19 +09:00

266 lines
6.1 KiB
C#

using UnityEngine;
using UnityEngine.Events;
public class PlayerChairSeat : MonoBehaviour
{
[Header("XR Player")]
public Transform xrOrigin;
public Camera xrCamera;
[Header("Seat Point")]
public Transform seatHeadPoint;
[Header("Release Point")]
public Transform releasePoint;
public bool moveToReleasePointOnRelease = true;
[Header("VR Interaction Check")]
public bool useDistanceCheck = true;
public float sitDistance = 2f;
[Header("Lock While Seated")]
public bool lockXROriginWhileSeated = true;
[Header("Release Move Check")]
public bool hideUIWhenPlayerMovesAfterRelease = true;
public float moveDetectDistance = 0.15f;
[Header("Disable Movement While Seated")]
public Behaviour[] disableWhileSeated;
[Header("Seat Interaction Zone")]
public GameObject[] disableObjectsAfterSeated;
public Collider[] disableCollidersAfterSeated;
public Behaviour[] disableBehavioursAfterSeated;
[Header("Events")]
public UnityEvent onSeated;
public UnityEvent onReleased;
public UnityEvent onMovedAfterRelease;
private bool isSeated = false;
private bool isReleased = false;
private bool movedAfterReleaseEventCalled = false;
private CharacterController characterController;
private Vector3 lockedOriginPosition;
private Quaternion lockedOriginRotation;
private Vector3 releaseOriginPosition;
void Start()
{
if (xrOrigin != null)
{
characterController = xrOrigin.GetComponent<CharacterController>();
}
SetSeatInteractionZoneActive(true);
}
void Update()
{
CheckMoveAfterRelease();
}
void LateUpdate()
{
if (!isSeated)
{
return;
}
if (!lockXROriginWhileSeated)
{
return;
}
if (xrOrigin == null)
{
return;
}
xrOrigin.position = lockedOriginPosition;
xrOrigin.rotation = lockedOriginRotation;
}
public void SitDown()
{
if (isSeated)
{
return;
}
if (xrOrigin == null || xrCamera == null || seatHeadPoint == null)
{
Debug.LogWarning("XR Origin / XR Camera / Seat Head Point ¿¬°á ¾È µÊ");
return;
}
if (useDistanceCheck)
{
float distance = Vector3.Distance(xrCamera.transform.position, seatHeadPoint.position);
if (distance > sitDistance)
{
Debug.Log("Too far from chair to sit.");
return;
}
}
isSeated = true;
isReleased = false;
movedAfterReleaseEventCalled = false;
foreach (Behaviour behaviour in disableWhileSeated)
{
if (behaviour != null)
{
behaviour.enabled = false;
}
}
if (characterController != null)
{
characterController.enabled = false;
}
float cameraYaw = xrCamera.transform.eulerAngles.y;
float targetYaw = seatHeadPoint.eulerAngles.y;
float yawOffset = targetYaw - cameraYaw;
xrOrigin.RotateAround(xrCamera.transform.position, Vector3.up, yawOffset);
Vector3 offset = seatHeadPoint.position - xrCamera.transform.position;
xrOrigin.position += offset;
lockedOriginPosition = xrOrigin.position;
lockedOriginRotation = xrOrigin.rotation;
if (characterController != null)
{
characterController.enabled = true;
}
SetSeatInteractionZoneActive(false);
Debug.Log("Player seated and locked.");
onSeated?.Invoke();
}
public void ReleaseSeat()
{
if (!isSeated)
{
Debug.Log("ReleaseSeat called, but player is not seated.");
return;
}
isSeated = false;
isReleased = true;
movedAfterReleaseEventCalled = false;
if (characterController != null)
{
characterController.enabled = false;
}
if (moveToReleasePointOnRelease && releasePoint != null && xrOrigin != null)
{
xrOrigin.position = releasePoint.position;
xrOrigin.rotation = releasePoint.rotation;
}
if (characterController != null)
{
characterController.enabled = true;
}
if (xrOrigin != null)
{
releaseOriginPosition = xrOrigin.position;
}
foreach (Behaviour behaviour in disableWhileSeated)
{
if (behaviour != null)
{
behaviour.enabled = true;
}
}
SetSeatInteractionZoneActive(true);
Debug.Log("Player released from seat.");
onReleased?.Invoke();
}
void SetSeatInteractionZoneActive(bool active)
{
foreach (GameObject obj in disableObjectsAfterSeated)
{
if (obj != null)
{
obj.SetActive(active);
}
}
foreach (Collider col in disableCollidersAfterSeated)
{
if (col != null)
{
col.enabled = active;
}
}
foreach (Behaviour behaviour in disableBehavioursAfterSeated)
{
if (behaviour != null)
{
behaviour.enabled = active;
}
}
}
void CheckMoveAfterRelease()
{
if (!hideUIWhenPlayerMovesAfterRelease)
{
return;
}
if (!isReleased)
{
return;
}
if (movedAfterReleaseEventCalled)
{
return;
}
if (xrOrigin == null)
{
return;
}
float distance = Vector3.Distance(xrOrigin.position, releaseOriginPosition);
if (distance >= moveDetectDistance)
{
movedAfterReleaseEventCalled = true;
Debug.Log("Player moved after release. Hide game UI.");
onMovedAfterRelease?.Invoke();
}
}
public bool IsSeated()
{
return isSeated;
}
}