using System; using UnityEngine.Assertions; using UnityEngine.XR.Interaction.Toolkit.Inputs; using UnityEngine.XR.Interaction.Toolkit.Locomotion; namespace UnityEngine.XR.Interaction.Toolkit { /// /// Locomotion provider that allows the user to smoothly rotate their rig continuously over time. /// /// /// [Obsolete("The ContinuousMoveProviderBase has been deprecated in XRI 3.0.0 and will be removed in a future version of XRI. Please use ContinuousTurnProvider instead.", false)] public abstract class ContinuousTurnProviderBase : LocomotionProvider { [SerializeField] [Tooltip("The number of degrees/second clockwise to rotate when turning clockwise.")] float m_TurnSpeed = 60f; /// /// The number of degrees/second clockwise to rotate when turning clockwise. /// public float turnSpeed { get => m_TurnSpeed; set => m_TurnSpeed = value; } bool m_IsTurningXROrigin; /// /// See . /// protected void Update() { m_IsTurningXROrigin = false; // Use the input amount to scale the turn speed. var input = ReadInput(); var turnAmount = GetTurnAmount(input); TurnRig(turnAmount); switch (locomotionPhase) { case LocomotionPhase.Idle: case LocomotionPhase.Started: if (m_IsTurningXROrigin) locomotionPhase = LocomotionPhase.Moving; break; case LocomotionPhase.Moving: if (!m_IsTurningXROrigin) locomotionPhase = LocomotionPhase.Done; break; case LocomotionPhase.Done: locomotionPhase = m_IsTurningXROrigin ? LocomotionPhase.Moving : LocomotionPhase.Idle; break; default: Assert.IsTrue(false, $"Unhandled {nameof(LocomotionPhase)}={locomotionPhase}"); break; } } /// /// Reads the current value of the turn input. /// /// Returns the input vector, such as from a thumbstick. protected abstract Vector2 ReadInput(); /// /// Determines the turn amount in degrees for the given vector. /// /// Input vector, such as from a thumbstick. /// Returns the turn amount in degrees for the given vector. protected virtual float GetTurnAmount(Vector2 input) { if (input == Vector2.zero) return 0f; var cardinal = CardinalUtility.GetNearestCardinal(input); switch (cardinal) { case Cardinal.North: case Cardinal.South: break; case Cardinal.East: case Cardinal.West: return input.magnitude * (Mathf.Sign(input.x) * m_TurnSpeed * Time.deltaTime); default: Assert.IsTrue(false, $"Unhandled {nameof(Cardinal)}={cardinal}"); break; } return 0f; } /// /// Rotates the rig by degrees. /// /// The amount of rotation in degrees. protected void TurnRig(float turnAmount) { if (Mathf.Approximately(turnAmount, 0f)) return; if (CanBeginLocomotion() && BeginLocomotion()) { var xrOrigin = system.xrOrigin; if (xrOrigin != null) { m_IsTurningXROrigin = true; xrOrigin.RotateAroundCameraUsingOriginUp(turnAmount); } EndLocomotion(); } } } }