Using the VR API

Updated 8 months ago

It is fun to have custom hand models, but abilities do need some changes in order to work well for VR. This part is going to cover the features of the VR API.

VR Checks

The VR API is meant to be used with the VR Mod. But, what happens if there is a dependency for the API and not the VR Mod? This is why it is important to check if the VR Mod is present before using the API's features. Here are different ways to check:

VR.enabled

This is a simple check for the presence of the VR Mod.

MotionControls.enabled

Always check for VR.enabled before this. Otherwise, there will be an error. This checks if the user has motion controls enabled in the VR Mod configs.

(entityState/characterBody/characterMaster).IsInVR()

This is an extension method in the Utils class that can be used on either an EntityState, CharacterBody or CharacterMaster. It checks for VR.enabled and makes sure the owner is the local client.

(entityState/characterBody/characterMaster).IsUsingMotionControls()

This is the same as IsInVR() but also checks for MotionControls.enabled.

Hands

You can access the player's hands in the MotionControls class. In the hands, there are useful things you can access too.

MotionControls.dominantHand / MotionControls.nonDominantHand

These are the hands you will use the most. They can be either the left or right hand depending on the player's VR Mod configs.

MotionControls.leftHand / MotionControls.rightHand

These hands do not take the player's configs into account. Note that you shouldn't use these hands for skills as they might not contain the hand prefab that you expect.

HandController class

These are the available properties you can access from hands.

transform

The transform is useful to retrieve the hand's position and rotation (not to confuse with the muzzle). It is also an easy way to call GameObject related methods.

muzzle

This returns the transform of the primary muzzle. This muzzle is used for aiming.

aimRay

Generates a Ray using the primary muzzle's forward direction. Useful for skills. Note that the dominant hand's aim ray can also be accessed with the normal GetAimRay() method.

animator

This is a quick way to access the animator on the hand object if there is one.

GetMuzzleByIndex(int index)

In case you have multiple muzzles apart from the primary one, you can use this method to get their transform.

Events

MotionControls.onHandPairSet

This event is called when the character body first spawns and the associated hands are loaded in.

Useful methods

MotionControls.AddHandPrefab(GameObject handPrefab)

As shown on the previous page, this adds a prefab for the VR Mod to instantiate on the player's hands. Use this on your prefabs from your asset bundle you have prepared in Unity.

MotionControls.AddHandSkin(ScriptableObject handSkinDef)

If you don't have direct access to the hand prefab, you can add hand skins using this method. This only accepts scriptable objects of type HandSkinDef.

MotionControls.AddSkillBindingOverride(string bodyName, SkillSlot dominantTrigger, SkillSlot nonDominantTrigger, SkillSlot nonDominantGrip, SkillSlot dominantGrip)

If you feel like a certain skill would make more sense to use with a different button from the default on a certain character, you can customize the buttons associated to each skill slot.

VR.AddVignetteState(Type stateType)

If your character has a high-mobility skill with quick movements, it is strongly recommended to make it use the confort vignette. Simply send the type of your EntityState using typeof(YourStateClass) and a black vignette will create a tunnel vision effect whenever this state is running. Even if you don't enjoy the vignette or don't get motion sick, some players prefer having the vignette during those kinds of skills. The vignette won't appear if the player chooses so in their configs.

VR.PreventRendererDisable(string bodyName, string rendererObjectName)

When playing in first person with the VR Mod, all renderers on the character get disabled for better visibility. You can prevent a certain renderer from being hidden by providing the body name and the name of the object containing said renderer.

Next step: Extra features