diff options
author | pryazha <pryadeiniv@mail.ru> | 2025-07-02 08:46:23 -0700 |
---|---|---|
committer | pryazha <pryadeiniv@mail.ru> | 2025-07-02 08:46:23 -0700 |
commit | 8263edd59284aba390aca011d25b79efecef4c48 (patch) | |
tree | 6346e2afaaabd32156601cafaf20d4ee813befaf /Assets/Samples/XR Interaction Toolkit/3.1.2/Starter Assets/Scripts/DynamicMoveProvider.cs |
Diffstat (limited to 'Assets/Samples/XR Interaction Toolkit/3.1.2/Starter Assets/Scripts/DynamicMoveProvider.cs')
-rw-r--r-- | Assets/Samples/XR Interaction Toolkit/3.1.2/Starter Assets/Scripts/DynamicMoveProvider.cs | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/Assets/Samples/XR Interaction Toolkit/3.1.2/Starter Assets/Scripts/DynamicMoveProvider.cs b/Assets/Samples/XR Interaction Toolkit/3.1.2/Starter Assets/Scripts/DynamicMoveProvider.cs new file mode 100644 index 0000000..033e5d4 --- /dev/null +++ b/Assets/Samples/XR Interaction Toolkit/3.1.2/Starter Assets/Scripts/DynamicMoveProvider.cs @@ -0,0 +1,190 @@ +using Unity.XR.CoreUtils; +using UnityEngine.Assertions; +using UnityEngine.XR.Interaction.Toolkit.Locomotion.Movement; + +namespace UnityEngine.XR.Interaction.Toolkit.Samples.StarterAssets +{ + /// <summary> + /// A version of continuous movement that automatically controls the frame of reference that + /// determines the forward direction of movement based on user preference for each hand. + /// For example, can configure to use head relative movement for the left hand and controller relative movement for the right hand. + /// </summary> + public class DynamicMoveProvider : ContinuousMoveProvider + { + /// <summary> + /// Defines which transform the XR Origin's movement direction is relative to. + /// </summary> + /// <seealso cref="leftHandMovementDirection"/> + /// <seealso cref="rightHandMovementDirection"/> + public enum MovementDirection + { + /// <summary> + /// Use the forward direction of the head (camera) as the forward direction of the XR Origin's movement. + /// </summary> + HeadRelative, + + /// <summary> + /// Use the forward direction of the hand (controller) as the forward direction of the XR Origin's movement. + /// </summary> + HandRelative, + } + + [Space, Header("Movement Direction")] + [SerializeField] + [Tooltip("Directs the XR Origin's movement when using the head-relative mode. If not set, will automatically find and use the XR Origin Camera.")] + Transform m_HeadTransform; + + /// <summary> + /// Directs the XR Origin's movement when using the head-relative mode. If not set, will automatically find and use the XR Origin Camera. + /// </summary> + public Transform headTransform + { + get => m_HeadTransform; + set => m_HeadTransform = value; + } + + [SerializeField] + [Tooltip("Directs the XR Origin's movement when using the hand-relative mode with the left hand.")] + Transform m_LeftControllerTransform; + + /// <summary> + /// Directs the XR Origin's movement when using the hand-relative mode with the left hand. + /// </summary> + public Transform leftControllerTransform + { + get => m_LeftControllerTransform; + set => m_LeftControllerTransform = value; + } + + [SerializeField] + [Tooltip("Directs the XR Origin's movement when using the hand-relative mode with the right hand.")] + Transform m_RightControllerTransform; + + public Transform rightControllerTransform + { + get => m_RightControllerTransform; + set => m_RightControllerTransform = value; + } + + [SerializeField] + [Tooltip("Whether to use the specified head transform or left controller transform to direct the XR Origin's movement for the left hand.")] + MovementDirection m_LeftHandMovementDirection; + + /// <summary> + /// Whether to use the specified head transform or controller transform to direct the XR Origin's movement for the left hand. + /// </summary> + /// <seealso cref="MovementDirection"/> + public MovementDirection leftHandMovementDirection + { + get => m_LeftHandMovementDirection; + set => m_LeftHandMovementDirection = value; + } + + [SerializeField] + [Tooltip("Whether to use the specified head transform or right controller transform to direct the XR Origin's movement for the right hand.")] + MovementDirection m_RightHandMovementDirection; + + /// <summary> + /// Whether to use the specified head transform or controller transform to direct the XR Origin's movement for the right hand. + /// </summary> + /// <seealso cref="MovementDirection"/> + public MovementDirection rightHandMovementDirection + { + get => m_RightHandMovementDirection; + set => m_RightHandMovementDirection = value; + } + + Transform m_CombinedTransform; + Pose m_LeftMovementPose = Pose.identity; + Pose m_RightMovementPose = Pose.identity; + + /// <inheritdoc /> + protected override void Awake() + { + base.Awake(); + + m_CombinedTransform = new GameObject("[Dynamic Move Provider] Combined Forward Source").transform; + m_CombinedTransform.SetParent(transform, false); + m_CombinedTransform.localPosition = Vector3.zero; + m_CombinedTransform.localRotation = Quaternion.identity; + + forwardSource = m_CombinedTransform; + } + + /// <inheritdoc /> + protected override Vector3 ComputeDesiredMove(Vector2 input) + { + // Don't need to do anything if the total input is zero. + // This is the same check as the base method. + if (input == Vector2.zero) + return base.ComputeDesiredMove(input); + + // Initialize the Head Transform if necessary, getting the Camera from XR Origin + if (m_HeadTransform == null) + { + var xrOrigin = mediator.xrOrigin; + if (xrOrigin != null) + { + var xrCamera = xrOrigin.Camera; + if (xrCamera != null) + m_HeadTransform = xrCamera.transform; + } + } + + // Get the forward source for the left hand input + switch (m_LeftHandMovementDirection) + { + case MovementDirection.HeadRelative: + if (m_HeadTransform != null) + m_LeftMovementPose = m_HeadTransform.GetWorldPose(); + + break; + + case MovementDirection.HandRelative: + if (m_LeftControllerTransform != null) + m_LeftMovementPose = m_LeftControllerTransform.GetWorldPose(); + + break; + + default: + Assert.IsTrue(false, $"Unhandled {nameof(MovementDirection)}={m_LeftHandMovementDirection}"); + break; + } + + // Get the forward source for the right hand input + switch (m_RightHandMovementDirection) + { + case MovementDirection.HeadRelative: + if (m_HeadTransform != null) + m_RightMovementPose = m_HeadTransform.GetWorldPose(); + + break; + + case MovementDirection.HandRelative: + if (m_RightControllerTransform != null) + m_RightMovementPose = m_RightControllerTransform.GetWorldPose(); + + break; + + default: + Assert.IsTrue(false, $"Unhandled {nameof(MovementDirection)}={m_RightHandMovementDirection}"); + break; + } + + // Combine the two poses into the forward source based on the magnitude of input + var leftHandValue = leftHandMoveInput.ReadValue(); + var rightHandValue = rightHandMoveInput.ReadValue(); + + var totalSqrMagnitude = leftHandValue.sqrMagnitude + rightHandValue.sqrMagnitude; + var leftHandBlend = 0.5f; + if (totalSqrMagnitude > Mathf.Epsilon) + leftHandBlend = leftHandValue.sqrMagnitude / totalSqrMagnitude; + + var combinedPosition = Vector3.Lerp(m_RightMovementPose.position, m_LeftMovementPose.position, leftHandBlend); + var combinedRotation = Quaternion.Slerp(m_RightMovementPose.rotation, m_LeftMovementPose.rotation, leftHandBlend); + m_CombinedTransform.SetPositionAndRotation(combinedPosition, combinedRotation); + + return base.ComputeDesiredMove(input); + } + } +} |