Search Unity

Question How to programmatically remove an interactable from a XRSocketInteractor

Discussion in 'XR Interaction Toolkit and Input' started by Devil_Inside, Jun 2, 2021.

  1. Devil_Inside

    Devil_Inside

    Joined:
    Nov 19, 2012
    Posts:
    1,119
    So I'm trying to create a scene where you load a cannonball into a cannon, which then shoots it.
    Cannonball is a XRGrabInteractable. Cannon is a XRSocketInteractor.
    You grab a cannonball from the crate, you place it into the cannon, the cannon shoots.
    My idea was that when the cannon shoots, I essentially remove the cannonball from the socket and places it back into the crate.

    The question is how can I programmatically remove an interactable from a socket?
    The first thing I tried is to set the socketActive property of the XRSocketInteractor to false, which causes the socket to deselect the cannonball (SelectExited events come with a weird several frame delay). I then move the cannonball back into the crate.
    The issue is when I then set the socketActive back to true, my recent cannonball gets teleported from the crate back into the cannon, as if it hasn't been properly deselected before.

    What would be the proper way to force the socket to deselect an interactable and properly "forget" about it so I can move it away?
     
    Stevie57 likes this.
  2. Devil_Inside

    Devil_Inside

    Joined:
    Nov 19, 2012
    Posts:
    1,119
    I found out that I have to wait for a fixed update before turning socketActive back on for the cannonball to not be teleported back into the cannon. However there is still some kind of issue of the socket not fully "releasing" the interactable, as it won't detect the next interaction.
    I've reported this as a bug, which was successfully reproduced by Unity QA: Issue Tracker
     
  3. WillemMahy

    WillemMahy

    Joined:
    Dec 18, 2016
    Posts:
    5
    You could try something like this?


    private IEnumerator MoveSelectedInteractable(XRBaseInteractable interactable, Vector3 newPosition)
    {
    // Store the interactable's interaction layer mask, in order to restore later on.
    var storeInteractionLayerMask = interactable.interactionLayerMask;

    // Make sure that the interactable gets unselected by the next update. (Hacky workaround, I know... :-/)
    interactable.interactionLayerMask = 0;

    yield return null; // Wait until next frame.

    // Socket interactor has now unselected the interactable.

    // Now move the interactable to its new position...
    interactable.gameObject.transform.position = newPosition;

    // ... and restore its interactionLayer mask.
    interactable.interactionLayerMask = storeInteractionLayerMask;

    yield break;
    }