using UnityEngine; using UnityEngine.XR.Interaction.Toolkit; public class SteeringKeyXR : MonoBehaviour { [Header("References")] [SerializeField] private UnityEngine.XR.Interaction.Toolkit.Interactables.XRGrabInteractable grabInteractable; [SerializeField] private Transform keyPivot; [Header("Steering")] [SerializeField] private float maxAngle = 45f; [Header("Return")] [SerializeField] private bool returnToCenter = true; [SerializeField] private float returnSpeed = 5f; private Transform currentInteractor; private bool isGrabbed; private Quaternion initialPivotRotation; private float currentAngle; public float SteeringValue { get { return Mathf.Clamp(currentAngle / maxAngle, -1f, 1f); } } private void Awake() { if (keyPivot == null) keyPivot = transform; initialPivotRotation = keyPivot.localRotation; } private void OnEnable() { if (grabInteractable != null) { grabInteractable.selectEntered.AddListener(OnGrab); grabInteractable.selectExited.AddListener(OnRelease); } } private void OnDisable() { if (grabInteractable != null) { grabInteractable.selectEntered.RemoveListener(OnGrab); grabInteractable.selectExited.RemoveListener(OnRelease); } } private void Update() { if (isGrabbed && currentInteractor != null) { UpdateAngleFromHand(); } else if (returnToCenter) { currentAngle = Mathf.Lerp(currentAngle, 0f, returnSpeed * Time.deltaTime); ApplyRotation(); } } private void OnGrab(SelectEnterEventArgs args) { isGrabbed = true; currentInteractor = args.interactorObject.transform; } private void OnRelease(SelectExitEventArgs args) { isGrabbed = false; currentInteractor = null; } private void UpdateAngleFromHand() { Vector3 worldDir = currentInteractor.position - keyPivot.position; Vector3 localDir = keyPivot.InverseTransformDirection(worldDir); float targetAngle = Mathf.Atan2(localDir.x, localDir.z) * Mathf.Rad2Deg; currentAngle = Mathf.Clamp(targetAngle, -maxAngle, maxAngle); ApplyRotation(); } private void ApplyRotation() { keyPivot.localRotation = initialPivotRotation * Quaternion.Euler(0f, currentAngle, 0f); } }