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(); } 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; } }