How to fly in Controller's forward direction?

Hello all,

with the Unity XR Interaction Toolkit, I am trying to realise a movement type that enables the player to fly around space in whatever direction the left controller points. For this, I have modified the ContinuousMoveProvider’s function ComputeDesiredMove like this:

    protected override Vector3 ComputeDesiredMove(Vector2 input)
    {
        if (input == Vector2.zero)
            return Vector3.zero;

        XRRig xrRig = system.xrRig;
        if (xrRig == null)
            return Vector3.zero;

        // Assumes that the input axes are in the range [-1, 1].
        // Clamps the magnitude of the input direction to prevent faster speed when moving diagonally,
        // while still allowing for analog input to move slower (which would be lost if simply normalizing).
        Vector3 inputMove = Vector3.ClampMagnitude(new Vector3(enableStrafe ? input.x : 0f, 0f, input.y), 1f);

        Transform rigTransform = xrRig.rig.transform;
        Vector3 rigUp = rigTransform.up;

        // Determine frame of reference for what the input direction is relative to
        Transform forwardSourceTransform = forwardSource == null ? xrRig.cameraGameObject.transform : forwardSource;
        Vector3 inputForwardInWorldSpace = forwardSourceTransform.forward;
        Quaternion forwardRotation = Quaternion.LookRotation(inputForwardInWorldSpace, forwardSource.up);

        Vector3 translationInRigSpace = forwardRotation * inputMove * (moveSpeed * Time.deltaTime);
        Vector3 translationInWorldSpace = rigTransform.TransformDirection(translationInRigSpace);

This works fine, but only until the XRRig changes its forward direction (via SnapTurnProvider). I am pretty sure this affects the calculations, but I am not sure in what way. Can anyone help me with this? I think this is something quite stupid about quaternions or transformation, but I don’t see the concrete problem right now.

Thanks in advance!

Hey @Nathaxx, I don’t have an answer to your question, but here is your code updated to work with the new XROrigin game object, which replaced XRRig.

< I had a problem with overriding the method, so modified the source. Yikes.>

I’m not using SnapTurn so your change works fine for me. Thanks,

        protected virtual Vector3 ComputeDesiredMove(Vector2 input)
        {
            if (input == Vector2.zero)
                return Vector3.zero;

            var xrOrigin = system.xrOrigin;
            if (xrOrigin == null)
                return Vector3.zero;

            // Assumes that the input axes are in the range [-1, 1].
            // Clamps the magnitude of the input direction to prevent faster speed when moving diagonally,
            // while still allowing for analog input to move slower (which would be lost if simply normalizing).
            var inputMove = Vector3.ClampMagnitude(new Vector3(m_EnableStrafe ? input.x : 0f, 0f, input.y), 1f);

            var originTransform = xrOrigin.Origin.transform;
            var originUp = originTransform.up;

            // Determine frame of reference for what the input direction is relative to
            var forwardSourceTransform = m_ForwardSource == null ? xrOrigin.Camera.transform : m_ForwardSource;
            var inputForwardInWorldSpace = forwardSourceTransform.forward;
            if (Mathf.Approximately(Mathf.Abs(Vector3.Dot(inputForwardInWorldSpace, originUp)), 1f))
            {
                // When the input forward direction is parallel with the rig normal,
                // it will probably feel better for the player to move along the same direction
                // as if they tilted forward or up some rather than moving in the rig forward direction.
                // It also will probably be a better experience to at least move in a direction
                // rather than stopping if the head/controller is oriented such that it is perpendicular with the rig.
                inputForwardInWorldSpace = -forwardSourceTransform.up;
            }

            //TLS Edits based on https://answers.unity.com/questions/1851515/how-to-fly-in-controllers-forward-direction.html

            var inputForwardProjectedInWorldSpace = forwardSourceTransform.forward; // Vector3.ProjectOnPlane(inputForwardInWorldSpace, originUp);
            //var forwardRotation = Quaternion.FromToRotation(originTransform.forward, inputForwardProjectedInWorldSpace);
            Quaternion forwardRotation = Quaternion.LookRotation(inputForwardInWorldSpace, forwardSource.up);

            var translationInRigSpace = forwardRotation * inputMove * (m_MoveSpeed * Time.deltaTime);
            var translationInWorldSpace = originTransform.TransformDirection(translationInRigSpace);

            return translationInWorldSpace;
        }