Showing the player's body in VR in Unity
Even though I published a Cheat Sheet for VR, I feel like showing the player's body is a topic of its own. Here goes.
Objective
My goal is to show the player body in a way that's believable, while minimizing the amount of work and code.
Adding a model
Drag and drop a model that represents the player's body. You can put it anywhere. I put it as a standalone object in my scene.
Positioning the body
Position
I assume that the body is positioned right below the head. This is not always the case as the player could be sitting back or leaning forward. But overall it works ok. Add a Position Constraint to the player model. Add the XRRig's Main Camera as the only Source. Make sure to check "Is Active".
In Constraint Settings, disable Y since you only want to copy the camera's X and Z position.
Model size
By the way, this method does not account for the player's height. To do this, you'd probably need a Script that scales the model so that its height is about Camera height + distance between the eyes and top of the head, maybe 20 cm. I haven't gotten around to implementing that yet.
Rotation
To make the body face in the right direction, I've found out through trial and error that you can approximate it with the position of your hands. Your chest tends to be parallel to the axis of your hands.
To implement that, I had the choice between a Look At Constraint (doc) and an Aim Constraint (see doc) to the player model. According to the documentation, the Look At Constraint is the simplified version of the Aim Constraint. Both will rotate the object so that it faces the weighted average of the Sources. It seems like it should do exactly what I wanted: if the player model faces the point between the left and right hands, the shoulders will face the same direction as the vector bewtween the left and right hands. However I wasn't able to set up the Look At Constraint to work correctly. So I went with the Aim Constraint: I set World Up Type to Scene Up, and added LeftHandController and RightHandController to the Sources.
This set up works pretty well, except when your hands are mostly vertical. If they happen to go slightly to your back, then the player model suddenly does a 180 with its body. It feels very strange.
To work around this, I added a 3rd source which I placed slightly in front of the camera. This way, unless you throw both your hands way behind your back, the player model will always face foward. This is how I set it up:
- Under the Main Camera, create a GameObject. I called it RotationTargetObject, but something like AimTargetObject would be more meaningful.
- Place it at z=.5, ie half a meter in front of the camera.
- Add that AimTargetObject to the sources of the AimConstraint.
- Make sure to check "Is Active".
- In Constraint Settings, uncheck both X and Z, so that the only rotation that will be computed is Y, which makes the model only turn left and right.
Positioning the hands
To do this, I use Inverse Kinematics. Read details about this at http://blog.wafrat.com/driving-characters-with-inverse-kinematics-in-unity/.
Applied to VR, I had to:
- Add a GameObject to each HandController to set up the offset.
- For each arm, in the Rig, add a Two Bone IK Constraint.
- The Source target is the hand controller offset.
Positioning the head
Again, I use Inverse Kinematics. Using the same method of setting an offset as in http://blog.wafrat.com/driving-characters-with-inverse-kinematics-in-unity/:
- Add a GameObject to the Main Camera, called HeadOffset.
- Adjust the HeadOffset so that when the player model's head matches HeadOffset, it is located exactly where the Main Camera is.
- In your Rig, add a GameObject called HeadConstraint.
- In HeadConstraint, add a Chain IK Constraint.
- The tip is the head.
- The root should be somewhere along your chest or spine. It's up to you how much of your spine you want to affect.
- Set the Source Target to be the HeadOffset.
By the way, the order of the constraints matter in the Rig. If your hand constraints are higher up, then they will be placed on their targets first, then the head constraints will alter the whole spine, thus your hands will not be where you expect them to be. To prevent this, make sure you put the head constraints before the hand constraints.
Handling the legs
Walking in a convincing fashion by taking steps is a topic in itself. See this video if you want to know how hard it is to make a character walk.
For now, since it's not critical for my gameplay, I went with simply hiding the legs by setting the scales of the lower body to zero.
Hide the body from the main camera
The reason why I wanted a body was so that I could see myself on a separate camera. In Main Camera, I don't actually want to see my body as the camera would be inside the head, and it would look really strange.
Here's how to hide the body in the Main Camera while making it visible in other cameras:
- Create a new layer called ThirdPersonView.
- Assign the player model's Mesh to the ThirdPersonView layer. You only need to assign the Mesh to the layer.
- In the Main Camera, in Culling Mask, uncheck ThirdPersonView.