Don't have an account? Join now...

How to open a VR door in Unity and SteamVR

- Intermediate Client Side Coding

In my VR business simulation Shopkeeper Simulator VR, hand interaction is generally achieved through the SteamVR Interaction System. Let's take a look at the 3D scene in Unity to visualize what we are going to talk about:

Fridge door in closed statae

Fridge door in closed state

Fridge door in opened state

Fridge door in opened state

Object hierarchy

To move the fridge door independently from the fridge body, the door was modeled as a separate mesh in Blender:

Fridge object hierarchy in Blender

Object hierarchy in Blender

After we exported the file as FBX, the imported hierarchy on the Unity side looked like this:

GameObject in Unity

Object hierarchy in Unity (irrelevant children obfuscated)

Handle explained

The "Handle" GameObject is the one which should react to the player's hand. Therefore, it was also separated from the door itself. The handle needs two components: The Interactable component which is part of the interaction system, a collider and the script OpenDoor which is explained further below.

Handle GameObject in the inspector

"Handle" GameObject in the inspector

Script OpenDoor.cs

using UnityEngine;
using Valve.VR.InteractionSystem;
  * This class is attached to a door handle. The door handle is child of a door.
 public class OpenDoor : MonoBehaviour
     private Vector3 force;
     private Vector3 cross;
     private bool holdingHandle;
     private float angle;
     private const float forceMultiplier = 150f;
     private void HandHoverUpdate(Hand hand)
         if (hand.GetStandardInteractionButton())
             holdingHandle = true;
             // Direction vector from the door's pivot point to the hand's current position
             Vector3 doorPivotToHand = hand.transform.position - transform.parent.position;
             // Ignore the y axis of the direction vector
             doorPivotToHand.y = 0;  
             // Direction vector from door handle to hand's current position
             force = hand.transform.position - transform.position;
             // Cross product between force and direction. 
             cross = Vector3.Cross(doorPivotToHand, force);
             angle = Vector3.Angle(doorPivotToHand, force);
         else if (hand.GetStandardInteractionButtonUp())
             holdingHandle = false;

     void Update()
         if (holdingHandle)
             // Apply cross product and calculated angle to
             GetComponentInParent<Rigidbody>().angularVelocity = cross * angle * forceMultiplier;
     private void OnHandHoverEnd()
         // Set angular velocity to zero if the hand stops hovering
         GetComponentInParent<Rigidbody>().angularVelocity =;

The two methods HandHoverUpdate and OnHandHoverEnd are specific to the SteamVR interaction system. They are called by the interaction system every frame the hand hovers over an interactable object and when the hovering ends respectively.

Basically, we are using the cross product of the force vector (pulling force of the hand) and the vector that points from the door's hinge to the transform where the hand is holding the handle (called "doorPivotToHand" vector). Together with the angle between the force vector and the "doorPivotToHand" vector, the angularVelocity is calculated and applied in FixedUpdate(). Note that FixedUpdate should be used and not Update, since we are changing a RigidBody's angular velocity.

Notice that in order to work, the door must have a Rigidbody, a collider and a Hinge Joint component to limit the door's angle. The HingeJoint's limits were set to 0 min and 90 max:


The GameObject "FridgeBody" needs a rigidbody with enabled isKinematic property and gravity equal false because we don't want the body to be controlled by the physics system and influenced by gravity. It is mandatory for the HingeJoint to work though.

I hope you found this little insight into our game Shopkeeper Simulator VR helpful for your own projects. If you found this useful, please leave a comment below and/or share the article! Also post any questions you might have.

In this Tutorial

Only registered members can share their thoughts. So come on! Join the community today and join in the conversation.

You are not logged in, join the community or sign in with your social account: