Unity VR : Doors and Drawers

Unity VR : Doors and Drawers

One of the best parts of VR is interacting with everyday objects and immersing ourselves into our environments. A common interaction to have is opening doors or drawers. They can be tricky to implement, but we’ll do our best to cover them here.

In this tutorial we’ll learn how to make a door in VR using a combination of Lever Joints and Grab Interactables. We’ll also cover how to prevent physics from interacting with our character collider so we don’t go flying when we open a door. Last we will cover how to make a drawers that can slide in and out!

 To follow along, download the Github project found here.

1 : Scene Review

Opening up the Scene we are greeted with two main items. We have a door that is surrounded by a door frame and a drawer. The door has 3 components, which are the door body and two door handles. The drawer is composed of 2 drawers which are themselves made up of multiple colliders so items can be placed inside them.

Besides that, we have our usual XR Origin that still have Direct and Ray Interactors on each hand. We also have a locomotion system that uses continuous movement with out left controller being for movement and right controller for turning. 

2 : Opening a Door

Let’s kick things off by getting our door to open. Thinking of first logical steps, we should probably be able to grab the handle to move the door. With that in mind, do the following.

  • Select the Door object in the Scene
  • Click Add Component -> XR Grab Interactable
  • On Rigidbody locate Collision Detection and choose Continuous Dynamic.
  • On XR Grab Interactable locate Movement Type and change it to Velocity Tracking.
  • On XR Grab Interactable locate Colliders and click the plus sign twice. Add DoorHandle1 and DoorHandle2 to the newly created slots.

What we’ve done so far is set up the Door to be a XR Grab Interactable. We changed the Rigidbody to Continuous Dynamic just in case our player move the door quickly so it will register physics correctly. We’ve also set the Movement Type to Velocity Tracking. This will make the door seem more real as when we let go, it will continue it’s velocity even when we’re no longer interacting with it. Finally, we have set up the two colliders to be used for the XR Grab Interactable to be the door handles.

If we started up the scene now, we’d be able to rip the door off the frame since it isn’t bound to anything. To fix this, we’re going to try a new component called the Hinge Joint. 

  • Click on the Door object in the Scene
  • Click Add Component and add a Hinge Joint
  • Locate the Hinge Joint component and do the following
    • Edit Angular Limits and click it so it appears in the Scene
    • Anchor and enter the following ( 0, 1, .4)
    • Axis and enter the following (0, 1, 0)
    • Use Limits and set it to True
    • Expand Limits and set Min = -120 and Max = 0. Leave the rest as their default
Going over what we just did, We added a Hinge Joint, which as its name implies, acts like a hinge on a door would. If you look in the Scene, you should see the angle that our door will open towards. By setting a limit, it will prevent the door from going in any direction. 
Starting up the Scene now, we should have a function door!

3 : Preventing Unwanted Physics Interactions

A problem we might run into when working with these doors are unwanted collisions with our Character Controller. Our Character Controller provides a Collider to our player so they can’t run through objects. If we were to grab the door and swing it towards us, it might launch ourselves across the room. In most games this isn’t an issue. In VR, it can be a nausea inducing pain. 

To prevent physics interactions like these, I’ve added a new layer called Body and have set the XR Origin to it. Notice that that children still remain on the default layer so our hands can still interact with objects.

I’ve also added two more Layers called Interactable and Interactable Ignore Ray.

Do the following to prevent physics interactions with the body using the door.

  • In the Scene, Select the Door object.
  • Change its layer to Interactable Ignore Ray, saying yes to setting all children to this layer as well.
  • Go to Edit -> Project Settings -> Physics
  • Unselect the box intersecting the Body and the Interactable and Interactable Ignore Ray.
Here we’ve set the layer for the door to be Interactable Ignore Ray. This layer will be used to have Grab Interactable that also ignore the Ray Interactor. It’d be silly to be able to grab a door from far away, so we’ve chosen to ignore it using this layer. 

Now if we start up the Scene, we should be able to grab the door without it launching us across the room.

4 : Making Drawers

Compared to doors, drawers are way more complicated. If we click on it and expand the children of the object, you’ll see numerous subsections to cover all the colliders we need to have the drawer function normally in terms of physics. 

Now we just need to be able to open the drawers. Let’s start with the Top Drawer.

  • Select the Top Drawer in the Scene
  • Add Component XR Grab Interactable
  • Set Layer to Interactable Ignore Ray
  • On Rigidbody, set Collision Detection to Continuous Dynamic.
  • On XR Grab Interactable 
    • Locate Colliders and click the plus sign. Drag the Handle object into the newly created slot.
    • Movement Type set to Velocity Tracking. 

Here we set up our drawer to be a grab interactable. We’ve also set it to a layer that prevents physics interactions with our Character Controller. We also set the only collider to be grabbable as our handle. Finally, we want to make sure our drawer has physics so we set the movement type to Velocity Tracking.

If we start up the scene now, we’ll be able to rip the drawer out and throw it wherever we want. Not exactly the behavior we’re after, but it is a start!

Next we need to set up a Configurable Joint to limit it from going in any direction.

  • Click Add Component and add a Configurable Joint
  • On Configurable Joint
    •  Edit Angular Limits, click the icon so we can visualize the joint in the scene
    • Anchor (0, .6, 0)
    • Axis (1, 0, 0)
    • X Motion = Locked
    • Y Motion = Locked
    • Z Motion = Limited
    • Angular X, Y, and Z Motion = Locked
    • Expand Linear Limit and set Limit to 0.4

We’ve done a lot here so let’s run through it. First we added a configurable joint to help limit movement. If we look in the Scene, we can see the orange arrow of the Configurable Joint pointing towards the X-axis in the scene giving us our orientation. Since it’s pointing towards the X-axis, we need the drawer to move on the Z-axis. With that in mind, we lock the motion for X, Y and we limit movement on the Z axis. We also lock down all angular motion for X, Y and Z since we don’t want the drawer to rotate. We finish by setting the Linear Limit to .4. This will allow the drawer to move both forwards and backwards from its initial position. Although the backwards motion isn’t wanted, it is prevented by a box collider in the back of the drawer.

It’s a lot to take in so feel free to experiment with Configurable Joints more to better understand them. It definitely took me a while to understand them.

Now when we start up the scene, we should have a working drawer.

The only problem is that it is a bit jagged when we grab it. Let’s try to smooth things out.

5 : Creating Better Drawers

To fix our drawers, lets try moving some components around. 

  • Select the TopDrawer
  • Remove the XR Grab Interactable Component
  • Select the Handle related to the TopDrawer
  • Add Component XR Grab Interactable to the Handle
  • On Rigidbody, set Collision Detection to Continuous Dynamic.
  • On XR Grab Interactable, set Movement Type to Velocity Tracking. 
Moving the XR Grab Interactable to our handle won’t be enough to fix this issue. Next we need to add a Fixed Joint. 
  • Select the Handle
  • Click Add Component and add a Fixed Joint.
  • On Fixed Joint, drag the TopDrawer object from the scene into the empty Rigidbody slot.

Fixed Joints will take whatever rigidbody it is associated with and use its joints instead. In this case, we still have the Configurable Joint on the TopDrawer object so the Fixed Joint will use that.

Now when we start up the scene, our drawers should be nice and smooth!

6 : Conclusion

With that, we’re all done! Make sure to use the bottom drawer as practice to get better implementing these things. This came with a lot of trial and error on my end and for a deeper understanding, make sure to experiment yourself!

2 thoughts on “Unity VR : Doors and Drawers”

  1. Hi, I love your tutorials. I am currently learning on VR development and your step by step tutorials really help me a lot! Is it possible to create one VR application (in Unity) and make it available across any VR headsets? Meaning at the early step on project setting, we make it available for all headsets.

Comments are closed.