AttachPoint wrong when using Instantaneous movement type in XRGrabInteractable.

In the XRToolkit example WorldInteractionDemo scene, I changed the movement type of the Jigsaw to “Instantaneous” instead of “Kinematic”.

It seems that objects no longer attach correctly to the hands:

Also, when placing the object into a socket, the attach point will be incorrect. I already filed a bug through the editor, but was wondering if anyone has a fix for this.

Thanks.

Hi @unitydreamer29 , can you share the case # of your bug report so I can make sure we’ve received it? Thanks.

Thanks @mfuad , just PM’d you.

I know in the previous version. Instananeous used the rigidbody center position as the attachpoint. So I wrote a simple script that set the RigidBody.CenterOfMass to the attachment point on OnSelectEnter and reset it on OnSelectExit.

That’s a great workaround @mikeNspired . I ended up copying the whole XRGrabInteractable.cs file and renaming it BetterXRGrabInteractable.cs and changing a few lines of code to actually have the component look for it’s AttachTransform.

// Added this function
private Vector3 GetAttachPosition()
{
    return this.attachTransform != null ? this.attachTransform.position : this.m_Rigidbody.worldCenterOfMass;
}

void PerformInstantaneousUpdate(XRInteractionUpdateOrder.UpdatePhase updatePhase)
{
    if (updatePhase == XRInteractionUpdateOrder.UpdatePhase.Dynamic ||
        updatePhase == XRInteractionUpdateOrder.UpdatePhase.OnBeforeRender)
    {
        if (trackPosition)
        {
            // transform.position = m_TargetWorldPosition;  // Replaced this line with below 2 lines
            var positionDelta = m_TargetWorldPosition - GetAttachPosition();
            transform.position += positionDelta;
        }
        if (trackRotation)
        {
            transform.rotation = m_TargetWorldRotation;
        }
    }
}

void PerformKinematicUpdate(XRInteractionUpdateOrder.UpdatePhase updatePhase)
{
    if (updatePhase == XRInteractionUpdateOrder.UpdatePhase.Fixed)
    {
        if (trackPosition)
        {
            // var positionDelta = m_TargetWorldPosition - m_Rigidbody.worldCenterOfMass;  // Replaced this line with the below line
            var positionDelta = m_TargetWorldPosition - this.GetAttachPosition();
         
            m_Rigidbody.velocity = Vector3.zero;
            m_Rigidbody.MovePosition(m_Rigidbody.position + positionDelta);
        }
        if (trackRotation)
        {
            m_Rigidbody.angularVelocity = Vector3.zero;
            m_Rigidbody.MoveRotation(m_TargetWorldRotation);
        }
    }
}

void PerformVelocityTrackingUpdate(float timeDelta, XRInteractionUpdateOrder.UpdatePhase updatePhase)
{
    if (updatePhase == XRInteractionUpdateOrder.UpdatePhase.Fixed)
    {
        // Do velocity tracking
        if (trackPosition)
        {
            // Scale initialized velocity by prediction factor
            m_Rigidbody.velocity *= k_VelocityPredictionFactor;
         
            // var posDelta = m_TargetWorldPosition - m_Rigidbody.worldCenterOfMass;  // Replaced this line with the below line
            var posDelta = m_TargetWorldPosition - this.GetAttachPosition();
         
            var velocity = posDelta / timeDelta;

            if (!float.IsNaN(velocity.x))
                m_Rigidbody.velocity += velocity;
        }

        // Do angular velocity tracking
        if (trackRotation)
        {
            // Scale initialized velocity by prediction factor
            m_Rigidbody.angularVelocity *= k_VelocityPredictionFactor;
            var rotationDelta = m_TargetWorldRotation * Quaternion.Inverse(m_Rigidbody.rotation);
            rotationDelta.ToAngleAxis(out var angleInDegrees, out var rotationAxis);
            if (angleInDegrees > 180f)
                angleInDegrees -= 360f;

            if (Mathf.Abs(angleInDegrees) > Mathf.Epsilon)
            {
                var angularVelocity = (rotationAxis * angleInDegrees * Mathf.Deg2Rad) / timeDelta;
                if (!float.IsNaN(angularVelocity.x))
                    m_Rigidbody.angularVelocity += angularVelocity * k_AngularVelocityDamping;
            }
        }
    }
}

It would be nice if XR Interaction Toolkit were in GitHub and I could pull request this.

Hope this helps!

1 Like

This Bug also extends to kinematic MovementType, when non-trigger-colliders are used.

@mfuad Are there any updates on when this will be fixed? Thanks for your work!

No specific ETA to share. Please give our teams some time to catch up from the holidays. Thanks.

Hello, Any updates on this subject? Instantaneous is the butter I seek but doesn’t like the attach transform I have set. I tried @brgishy 's method but with no avail, possibly because of the tool kit version I am using 1.0.0 pre 3.

anyway if anyone can shed some light on it that would be amazing :smile:
cheers

Seems related to (or the same as?) the problem I had before christmas: XRBaseInteractable attachtransform incorrect attaching

This is how I fixed it: https://github.com/fresolina/com.unity.xr.interaction.toolkit/commit/d80549fa3d9ddfe7e8a4e966059f993296ef58fb

TBH I couldn’t make sense of how the original code was functioning. I haven’t actually checked if pre3 has fixed this or not, but at least there were no changes in that code, so I assumed not.

1.0.0-pre.3 does not have the fix for this as I have just this moment encountered the issue.
@mfuad any updates on this? I switched from Oculus Integration due to the equivalent feature being completely broken, was very pleased to see XRITK work intuitively with the attachTransforms for snap-grabbing until I tried Instantaneous movementType.

I believe they have fix in the 1.0.0-pre.4 ready.

1 Like

@GohanCZ Oh nice! I used this workaround for now if anyone is interested. Instantaneous Attach Transforms not lining up correctly

1 Like

Where did you see information about what is coming with 1.0.0-pre.4?

On the issue tracker

1 Like

Yep. Exactly there. Stumbled upon it when googling the issue myself.

Confirmed fixed on 1.0.0-pre.4, thanks Unity team.

One comment about the legacy attach setting, it might be nice to keep that instead of deprecating it. I’m using XRGrabInteractables on objects attached to hinge joints, and the legacy attach point option works a lot better for these type of objects for some reason. Haven’t dug into why yet.