The HTC Vive headset needs specific code before we can pick up and grab objects in our apps. In this article we’ll go over that required code, assigning functions to controller buttons, and to get your hands dirty in Vive’s virtual sandbox.

With Vive’s room-scale VR and lightweight controllers, grabbing and manipulating objects makes you feel like you’re truly immersed. This article will review and explain the code and parent-child relationship you’ll include to build an interactive virtual world. But this is just the beginning — our 10-week course covers everything you need to know, in-depth and with 1:1 training, to get creating. For now, let’s get your Vive controllers ready to use.

Download our 10-week VR Development with Unity Course Syllabus


 

Skip to the Technical Steps

 

Getting Started

 
It’s important to clarify that the code we outline here uses a parent-child relationship in order for objects to be picked up. The other option is through a physics relationship, which we go over in our article on grabbing and shooting objects with HTC Vive. It’s important to not mix and match relationships, so just a heads up!

To get Unity primed and ready for these steps, we’ll have to make sure we have the SteamVR Asset downloaded into Unity. We cover this in depth in this article here, as well as how to start a new C# script.

After making a new C# script in Unity and label it something unique (eg ViveGrabObject) and you’ll have the following start to your code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class ViveGrabObject : MonoBehaviour {

To get started creating with the Vive controller, you’ll need to write some code. In essence this next step will create a shortcut when it comes to assigning functions to buttons.

    private SteamVR_TrackedObject trackedObj;
    private SteamVR_Controller.Device Controller
    {
        get
        {
            return SteamVR_Controller.Input((int)trackedObj.index);
        }
    }
    void Awake()
    {
        trackedObj = GetComponent<SteamVR_TrackedObject>();
    }

Great job! Now, we want to track what objects with rigidbodies we are grabbing:

    public GameObject collidingObject;

As well as tracking the specific object we’re grabbing:

    public GameObject objectInHand;

You’ll need to set your controllers to be trigger zones for the following functions. So, head to your controllers in Unity’s hierarchy page, and add component. Scroll down to Physics and select Sphere Collider, and select the Trigger checkmark.


Great! Now let’s add the following functions:

void OnTriggerEnter(Collider other)
{
	if (!other.GetComponent<Rigidbody>())
	{
		return;
	}
}

If the object does have a rigidbody, we’ll want to assign it to our collidingObject variable, so we know we can interact with it:

collidingObject = other.gameObject;

Once we leave a trigger zone, you can set the object to be removed from our hands with the following. You’ll also need to set the collidingObject variable to null:

void OnTriggerExit(Collider other)
{
	collidingObject = null
}

Last but not least, We’ll want to update the responsiveness of our controllers so when pushing our grip button to pick up an object, there’s no delay:

Void Update ()
{
	if (collidingObject)
	{
		GrabObject ();
	}
}

Similarly, if you let go of the grip buttons when already holding an object, you’ll need to include a ReleaseObject function:

if (Controller.GetPressUp (SteamVR_Controller.ButtonMask.Grip))
{
	if (objectInHand)
	{
		ReleaseObject ();
	}
}

 

Pick Me Up! Put Me Down!

 
Now that the prep work is done, we can get down to business! (The business of actually grabbing and releasing objects).

Once the object is grabbed, we’ll need to add the object to our objectInHand variable, set the object to follow the controller’s movements, and be resistant to forces like gravity while still being able to apply its own forces when colliding with other objects:

private void GrabObject()
{
	objectInHand = collidingObject;
	objectInHand.transform.SetParent (this.transform);
	objectInHand.GetComponent<Rigidbody>().isKinematic = true;
}

To release the object and allow gravity and other forces able to affect the object again, use the following:

private void ReleaseObject()
{
	objectInHand.GetComponent<Rigidbody&gt().isKinematic = false;
	objectInHand.transform.SetParent (null);
	}
}
[/csharp]

Victory!

 
We can now pick up, use, and drop objects in your VR program. More interactivity means more immersion, and ultimately makes for a better VR application. Good job!

We teach people of any skill level how to use Unity to create VR and AR worlds. Get building, and take a look at what our 10-week course with 1:1 mentorship looks like by downloading our syllabus.

Download VR Course Syllabus

Technical Steps:

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class ViveGrabObject : MonoBehaviour {
    private SteamVR_TrackedObject trackedObj;
    private SteamVR_Controller.Device Controller
    {
        get
        {
            return SteamVR_Controller.Input((int)trackedObj.index);
        }
    }
    void Awake()
    {
        trackedObj = GetComponent<SteamVR_TrackedObject>();
    }
 
    public GameObject collidingObject;//To keep track of what objects have rigidbodies
    public GameObject objectInHand;//To track the object you're holding

    void OnTriggerEnter(Collider other)//Activate function in trigger zone, checking rigidbodies and ignoring if no rigidbodies 
    {
        if (!other.GetComponent<Rigidbody>())
        {
            return;
        }
        collidingObject = other.gameObject;//If rigidbody, then assign object to collidingObject variable
  }
 
    void OnTriggerExit(Collider other)
    {
        collidingObject = null;
    }

    void Update ()
    {
        if (Controller.GetPressDown (SteamVR_Controller.ButtonMask.Grip))// Push grip buttons and touching object, set GrabObject function
        {
            if (collidingObject)
            {
                GrabObject ();
            }
        }  
        if (Controller.GetPressUp (SteamVR_Controller.ButtonMask.Grip))// If release grip buttons and holding object, set to release
        {
            if (objectInHand)
            {
                ReleaseObject ();
            }
        }
    }

    private void GrabObject() // Picking up object and assigning objectInHand variable
    {
        objectInHand = collidingObject;
        objectInHand.transform.SetParent (this.transform);
        objectInHand.GetComponent<Rigidbody>().isKinematic = true;
    }
// Releasing object and disabling kinematic functionality so other forces can affect object
    private void ReleaseObject()
    {
        objectInHand.GetComponent<Rigidbody>().isKinematic = false;
        objectInHand.transform.SetParent (null);
    }
}
[/csharp]