Forum Discussion

🚨 This forum is archived and read-only. To submit a forum post, please visit our new Developer Forum. 🚨
DeakinCUBE's avatar
DeakinCUBE
Explorer
6 years ago
Solved

How can I toggle (enable / disable) OVRGrabbable on a Unity game object in script?

I would like to toggle OVRGrabbale on a game object, subject to a boolean condition.  

As an example, a virtual "screw":
- when it is screwed into a hole (engaged), it SHOULD NOT be grabbable by the player
- when it is unscrewed (dis-engaged), it SHOULD be grabbable by the player

My understanding is the boolean attribute "allowOffhandGrab" can / should be used for this, however this attribute is only read-only in OVRGrabbable.cs.

Adding a setter in OVRGrabbable.cs has not had any effect on disabling OVRGrabbable during runtime.

/// <summary>
/// If true, the object can currently be grabbed.
/// </summary>
    public bool allowOffhandGrab
    {
        get { return m_allowOffhandGrab; }
        set { m_allowOffhandGrab = value; }     // Added to test grabbablity switching (ie. on / off) but does not seem to work
    }

As a partial workaround solution, I've also tried enabling / disabling the game object's collider and rigidbody.detection components.  Both of these work by allowing me to toggle the object's "grabbability" however creates interactivity issues with other game objects, so is not a feasible solution.

Can someone please help?

Thank you.
  • I've managed to solve it...turns out it was very easy but requires changes to OVRGrabbable.cs and OVRGrabber.cs

    For anyone else who comes across this problem:

    Step 1)
    In OVRGrabbable.cs
       
        public bool allowOffhandGrab
        {
            get { return m_allowOffhandGrab; }
            set { m_allowOffhandGrab = value; }     // Add this line to allow write-access to attribute
        }


    Step 2)
    In OVRGrabber.cs:

        protected virtual void GrabBegin()
        {
            float closestMagSq = float.MaxValue;
            OVRGrabbable closestGrabbable = null;
            Collider closestGrabbableCollider = null;

            // Iterate grab candidates and find the closest grabbable candidate
            foreach (OVRGrabbable grabbable in m_grabCandidates.Keys)
            {
                //bool canGrab = !(grabbable.isGrabbed && !grabbable.allowOffhandGrab);         // was this
                bool canGrab = !grabbable.isGrabbed && grabbable.allowOffhandGrab;              // change to this

                if (!canGrab)
                {
                    continue;
                }

    Step 3)
    Now you can toggle OVRGrabbable on/off in script by referencing the OVRGrabbable script and then setting "allowOffHandGrab" to true (can grab) or false (cannot grab)

    Eg:

        public class Screw : MonoBehaviour
        {
            private OVRGrabbable _OVRGrabbable;

           private void Awake()
            {
                _OVRGrabbable = GetComponent<OVRGrabbable>();
            }

            public void ToggleGrab(bool value)
            {
                _OVRGrabbable.allowOffhandGrab = value;    // True = can grab; False = cannot grab
            }
        }

    Hope this helps anyone else who encounters this problem.
    :-)

8 Replies

  • I've managed to solve it...turns out it was very easy but requires changes to OVRGrabbable.cs and OVRGrabber.cs

    For anyone else who comes across this problem:

    Step 1)
    In OVRGrabbable.cs
       
        public bool allowOffhandGrab
        {
            get { return m_allowOffhandGrab; }
            set { m_allowOffhandGrab = value; }     // Add this line to allow write-access to attribute
        }


    Step 2)
    In OVRGrabber.cs:

        protected virtual void GrabBegin()
        {
            float closestMagSq = float.MaxValue;
            OVRGrabbable closestGrabbable = null;
            Collider closestGrabbableCollider = null;

            // Iterate grab candidates and find the closest grabbable candidate
            foreach (OVRGrabbable grabbable in m_grabCandidates.Keys)
            {
                //bool canGrab = !(grabbable.isGrabbed && !grabbable.allowOffhandGrab);         // was this
                bool canGrab = !grabbable.isGrabbed && grabbable.allowOffhandGrab;              // change to this

                if (!canGrab)
                {
                    continue;
                }

    Step 3)
    Now you can toggle OVRGrabbable on/off in script by referencing the OVRGrabbable script and then setting "allowOffHandGrab" to true (can grab) or false (cannot grab)

    Eg:

        public class Screw : MonoBehaviour
        {
            private OVRGrabbable _OVRGrabbable;

           private void Awake()
            {
                _OVRGrabbable = GetComponent<OVRGrabbable>();
            }

            public void ToggleGrab(bool value)
            {
                _OVRGrabbable.allowOffhandGrab = value;    // True = can grab; False = cannot grab
            }
        }

    Hope this helps anyone else who encounters this problem.
    :-)
  • Have the same issue and tried your solution but it does not seem to matter if the allowOffhandGrab is true or false (either from inspector nor script). It is always grabable.

    Although documentation states that it should disable the grabbing. 
    Strange.

    Unity v2019.3.0f3, Oculus Utilities v1.44.0, OVRPlugin v1.44.0, SDK v1.44.0.
  • nZer0_'s avatar
    nZer0_
    Honored Guest

    In my case, with DistanceGrabber, I added Step 4 and it solved.

    Step 4)
    In DistanceGrabber.cs 

           protected bool FindTarget(out DistanceGrabbable dgOut, out Collider collOut)
            {
                dgOut = null;
                collOut = null;
                float closestMagSq = float.MaxValue;

                // First test for objects within the grab volume, if we're using those.
                // (Some usage of DistanceGrabber will not use grab volumes, and will only 
                // use spherecasts, and that's supported.)
                foreach (OVRGrabbable cg in m_grabCandidates.Keys)
                {
                    DistanceGrabbable grabbable = cg as DistanceGrabbable;
                    //bool canGrab = grabbable != null && grabbable.InRange && !(grabbable.isGrabbed && !grabbable.allowOffhandGrab);   // was this
                    
    bool canGrab = grabbable != null && grabbable.InRange && (!grabbable.isGrabbed && grabbable.allowOffhandGrab);

    if (canGrab && m_grabObjectsInLayer >= 0) canGrab = grabbable.gameObject.layer == m_grabObjectsInLayer;
                    if (!canGrab)
                    {
                        continue;
                    }
  • Hi juruhn

    Sorry I just saw your reply.  Did you manage to solve your issue?
  • Hi DeakinCUBE,

    Due to time pressure, I made a workaround. 
    As I exactly know when they need to be grabable and not, I just add and remove the OVRGrabbable script to the object.

    There were a few updates by now, so maybe the issue is fixed. Haven't tested it yet.
    Happy to hear others experiences with the OVRGrabbable.

  • Hi Juruhn,

    Glad to hear you got it working.  For something as fundamental as being able to restrict / allow vr grabbing of certain objects as circumstances require (in real time), it seems odd to me that Oculus have not incorporated this into their scripts - we're talking a couple of lines of code.


  • Totally agree, that's why I was really surprised and thought I was missing something.
    For now it works with current solution, but I will look into it later, there must be a 'ready to go' solution provided that actually works out of the box. (although its new technology)
  • Jecey's avatar
    Jecey
    Honored Guest

    Writing this in case people still encounter this issue. Personally I found it more effective to make a subclass of OVRGrabbable by inheriting it instead of inheriting Monobehaviour. This allows you to make edits to some of the member variables without needing to change the library code while also allowing you to override from GrabBegin and GrabEnd for more flexibility.