Flexible Grab Point

I am using XR Grab Interactable and when I pick an object up, either with ray or a collider on the hand, it picks it up either from the middle or from the attach transform (like an empty gameobject) that I manually set. Is it possible to grab an object from wherever the ray hits it or the hand collides with it?
I also noticed that when I grab something, it auto rotates the object based on the hand. I want the object to track the rotation changes, but I don’t want it to reset the rotation every time I pick it up. In other words, i want to be able to grab and rotate the object, let it go (it’s kinematic), and pick it up while it holds the current rotation so I can rotate it again or more or do whatever else. I feel like there should be a pre-made grab method for this but I can’t find it. I don’t even know what to Google to find some guidance on this. Any help would be much appreciated.

1 Like

Hi @AnahidE5 ,
We are currently working on support for this in the next minor release of the XR Interaction Toolkit (2.1.0). I don’t have an exact date on the release of 2.1.0, but it will likely be in the next couple of months.

Hi Dave. I tested 2.1.0 but I can’t figure out how to enable the support for what we talked about above. Is it related to the “Use dynamic attach” setting and if it is, how can i make it work? I tried different settings and still the rotation is automatically changed every time i grab the object. Thanks.

With 2.1.0 of XRI, enable Use Dynamic Attach in the Inspector window of your XR Grab Interactable. By default, Match Position and Match Rotation will both already be enabled which should allow the position and rotation to be set so it doesn’t cause any initial movement when you grab it.

Note that if you are using an XR Ray Interactor with Force Grab enabled, the dynamic attach pose will be the same as the static attach pose on the XR Grab Interactable instead of being based on the hit position. This is because we assume if you want to bring the object to your hand, it should not stay at a far distance which is what would happen if the dynamic attach calculated the offset relative to that attach position. If you want to keep the object where it is, you’ll need to disable Force Grab on your XR Ray Interactors.

Thanks a lot for the explanation. What about having it come close but keep the original rotation? I disabled force grab, enabled Use Dynamic Attach and Match rotation thinking the position will change but the object will keep the rotation but it also keeps its position instead of moving to the hand. Is there another setting overriding that? Thanks again.

At the moment, the XR Grab Interactable ignores the Match Position and Match Rotation when the interactor grabbing it is an XR Ray Interactor with Force Grab enabled. If you want to change that, you’ll need to create a new script that derives from XRGrabInteractable and override the InitializeDynamicAttachPose method, copy the code from the base class and remove the early return check for interactor is XRRayInteractor rayInteractor && rayInteractor.useForceGrab. You’ll have to change some of the variables to use the property name instead of the field name when you copy-paste. Then you can disable Match Position and keep Match Rotation enabled and it will achieve what you want.

I made a task for our team to look into either updating the API to make the conditions easier to override, or modify the method so it allows you to keep the rotation but ignores the value of Match Position when Force Grab is enabled. Our assumption was that if Force Grab was enabled, users would want it to always go to the fixed static attach pose set on the Interactor, but it sounds like that’s not the case. We’ll try to make that update before the final 2.1.0 release.

1 Like

Any update on this? Did the force grab + dynamic attach end up becoming an optional feature? I would like to have both. Also in your instructions I am not sure what you mean by changing variables to use property name instead of the field name.

The change I mentioned made it into the 2.1.1 release, so you shouldn’t need to override InitializeDynamicAttachPose like I mentioned in my earlier post to get that desired behavior:

As for the copy-paste thing I was talking about, I meant that if you copied the method into a custom derived class to tweak part of it, you could copy the entire contents but you would need to replace the private fields like m_MatchAttachPosition with public properties like matchAttachPosition in your derived class for it to compile.

1 Like

Hello :slight_smile:

Which settings do I need for this scenario:
I have a ray interactor with force grab. If I grab my cube object in the scene I want it to match the original rotation but snap to my controller model at that point where the ray attached the cube. If I use dynamic attach and only check the ‘match rotation’, the cube will come to the controller but it snaps at the middle of the object not at the original attachment point.

The assumption was that if Force Grab is enabled, we always treat Match Position as disabled since otherwise the object wouldn’t move to your hand because of the way the attach transforms are initialized. However as you’ve seen, that means the object will always snap using its pivot point instead of based on the ray hit position.

The easiest way to get the behavior you want would be to set Force Grab to false, and then instead add this component to the Ray Interactor to make the object effectively come to your hand. Then expand the Interactor Events foldout, add a listener to the Select Entered event, and call the method in that component. The Grab Interactable should have Match Position and Match Rotation enabled. This setup will allow the Grab Interactable to come to your hand based on the hit point.

The script works by resetting the Ray Interactor’s attach transform back to where it was the moment before the Ray Interactor sets it to the hit position upon select, which is back at the hand. This will be done after the Grab Interactable can read the hit position to make it match correctly.

using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;

public class ResetAttachTransform : MonoBehaviour
{
    public void ResetAttachTransformPosition(SelectEnterEventArgs args)
    {
        if (args.interactorObject is XRBaseInteractor baseInteractor)
        {
            baseInteractor.GetAttachTransform(args.interactableObject).localPosition =
                baseInteractor.GetLocalAttachPoseOnSelect(args.interactableObject).position;
        }
    }
}

9841650--1416054--Select Entered reset.png

1 Like