VR in Unity: Managing Controller Input and Hand Presence (Part 2: Creating Animated Hands)
This guide is a continuation of my last post how to handle VR controller input and will focus on creating animated hand controllers instead of using the standard 3D controller models.
Set Up the Hand Models
In our hand presence script we create three new variables. We create a public gameobject variable to store our hand model prefab, a public bool to control whether we are showing the controller or the hand model, and a private gameobject to store our spawned hand model.
In void Start() we declare our spawnedHandModel variable as an instantiation of our handModelPrefab:
Then in the Update() function we create a simple bool check to control whether we spawn in our hand model or our controller:
Now on the left and right HandPresence prefabs we drag in the associated left and right hand models to the designated fields. If you do not have hand models yet, you can download the Oculus Hands package below:
With the showController bool set to false our hands are properly displaying in place of the controllers.
Animate Hands According to Player Input
Depending on the hand assets you download you may or may not already have an animator set up on the prefabs as well as a number of preset animations. The Oculus package includes both the controllers and animation packages. If you do not already have an Animator component on your hands proceed to create one as well as an Animator Controller. Assign the controller to the Animator component and repeat for both hands.
Open the Animator window and create two new float Parameters — Grip and Trigger. Right click in the Animator tree and Create State -> From New Blend Tree. Double click on the blend tree and in the Inspector update the Blend Type to 2D Freeform Cartesian. Set the first parameter to Grip and the second to Trigger.
In the Motion list create 4 new motion states and set the values to: (0,0)(0,1)(1,0)(1,1). Now we can drag in the associated poses from our Oculus package. Be sure to note whether you are working from the right or left animation controller as the animations are specific to each hand.
Into each field drag the blue triangle subcomponent for each animation.
In position 1 we add right hand default animation to represent no grip and no trigger behavior.
In position 2 we are pinching but have no grip, and we drag in the right pinch pose.
In position 3 we are gripping only and can use the squirtgun squeeze pose here for a half grip.
In position 4 we are both gripping and pinching so we use the tightened fist pose here.
We can drag in our right hand model to the preview area to preview the animation between states:
For the left hand we can duplicate the controller and update the animations to the left hand variations.
Be sure your default state is set to move from entry to the blend tree and we are ready to implement the code logic. Back in the HandPresence script create a new private animator variable for handAnimator and assign it in void Start().
For now comment out all of the if statements currently in the update function. Instead we will create a new function for UpdateHandAnimation() and add the trigger input check logic here instead:
We copy the same logic for grip inside this same method. This method will check for our input for both the trigger and grip buttons and update our blend tree as needed to match the 0 to 1 float scale for each button.
Finally, we call this function when we are not showing the controllers in the update function:
Voila! We have hand tracking behavior that feels responsive and gives the player feedback on the actions they are taking within our game.
One additional feature you may want to add to prevent errors is to call the controller initialization again after void Start(). The reason for this is that sometimes controllers will not register right at void start but only after they are picked up. We reinitialize this in the event it fails by moving all of our start method code to a new function (TryToInitialize()) and after calling it in Start, calling it again in update if it fails:
The syntax “!targetDevice.isValid” will check if we have a device and return true if no controllers are found, at which point we run the initialize code again. We also put the controller vs hands bool check into an else statement to be sure this runs after our devices have been found.
All set! I hope you enjoyed this guide on setting up animated hand controllers for VR in Unity. In my next guide I’ll tackle creating a teleportation system. See ya there!