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
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.
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
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.
- 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!
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.
Unity covers development for the majority of VR headsets thanks to OpenXR. I kind of cover how to deploy to multiple headsets in this video. I’ve set the timestamp to specifically what you’re asking about.
https://youtu.be/ojZkl8q3YBI?t=343
If you want to learn more about OpenXR and what it is, you can find more info here!
https://www.khronos.org/openxr/
Cheers!