using UnityEngine; using UnityEngine.InputSystem; public class PlayerMovement : MonoBehaviour { [Header("Movement")] [SerializeField] private float speed = 3f; [Header("VR Camera Reference")] [Tooltip("XR Origin > Camera Offset > Main Camera를 넣으세요.")] [SerializeField] private Transform cameraTransform; [Header("Move Input Actions")] [Tooltip("Dynamic Move Provider가 쓰는 Left Move Input과 같은 액션을 넣으세요.")] [SerializeField] private InputActionReference leftMoveAction; [Tooltip("Dynamic Move Provider가 쓰는 Right Move Input과 같은 액션을 넣으세요.")] [SerializeField] private InputActionReference rightMoveAction; [Header("Reverse Control")] [SerializeField] private bool isReversed = false; [Header("External Move Provider")] [Tooltip("XR Origin > Locomotion > Move에 있는 Dynamic Move Provider 컴포넌트를 넣으세요.")] [SerializeField] private Behaviour dynamicMoveProvider; public bool IsReversed => isReversed; public Vector2 CurrentInput { get; private set; } public Vector2 CurrentOutput { get; private set; } private CharacterController characterController; private void Awake() { characterController = GetComponent(); ApplyMoveMode(); } private void OnEnable() { EnableAction(leftMoveAction); EnableAction(rightMoveAction); ApplyMoveMode(); } private void Update() { CurrentInput = ReadMoveInput(); CurrentOutput = isReversed ? -CurrentInput : CurrentInput; // 일반 상태에서는 Dynamic Move Provider가 이동하므로 이 스크립트는 이동하지 않음 if (!isReversed) return; Move(CurrentOutput); } private void Move(Vector2 input) { if (cameraTransform == null) return; if (input.sqrMagnitude < 0.0001f) return; Vector3 forward = cameraTransform.forward; Vector3 right = cameraTransform.right; forward.y = 0f; right.y = 0f; forward.Normalize(); right.Normalize(); Vector3 moveDirection = right * input.x + forward * input.y; Vector3 movement = moveDirection * speed * Time.deltaTime; if (characterController != null && characterController.enabled) { characterController.Move(movement); } else { transform.position += movement; } } private Vector2 ReadMoveInput() { Vector2 leftInput = ReadAction(leftMoveAction); Vector2 rightInput = ReadAction(rightMoveAction); if (leftInput.sqrMagnitude >= rightInput.sqrMagnitude) return leftInput; return rightInput; } private Vector2 ReadAction(InputActionReference actionReference) { if (actionReference == null || actionReference.action == null) return Vector2.zero; return actionReference.action.ReadValue(); } private void EnableAction(InputActionReference actionReference) { if (actionReference == null || actionReference.action == null) return; if (!actionReference.action.enabled) actionReference.action.Enable(); } public void SetReversed(bool value) { isReversed = value; ApplyMoveMode(); } public void ToggleReversed() { isReversed = !isReversed; ApplyMoveMode(); } private void ApplyMoveMode() { if (dynamicMoveProvider != null) { dynamicMoveProvider.enabled = !isReversed; } } }