Home

Awesome

SteamVR Unity Toolkit

A collection of useful scripts and prefabs for building SteamVR titles in Unity 5.

This Toolkit requires the SteamVR Plugin from the Unity Asset Store to be imported into your Unity project.

Note:

This is very early alpha and does not offer much functionality at present. I'm open to suggestions, ideas and bug finding/fixing. Also, expect builds to break older versions as things are changing fast at this stage, it will settle down when the project reaches a beta stage.

Quick Start

FAQ/Troubleshooting

Summary

This toolkit provides many common VR functionality within Unity3d such as (but not limited to):

The toolkit is heavily inspired and based upon the SteamVR Plugin for Unity3d Github Repo.

The reason this toolkit exists is because I found the SteamVR plugin to contain confusing to use or broken code and I decided to build a collection of scripts/assets that I would find useful when building for VR within Unity3d.

What's In The Box

This toolkit project is split into two main sections:

The SteamVR_Unity_Toolkit directory is where all of the relevant files are kept and this directory can be simply copied over to an existing project. The Examples directory contains useful scenes showing the SteamVR_Unity_Toolkit in action.

Prefabs

The available Prefabs are:

[CameraRig]

The [CameraRig] has been taken directly from the SteamVR Unity plugin example: Extras/SteamVR_TestThrow scene as it includes the relevant Model children on the controller (which seem to be missing from the default prefab in the SteamVR plugin Prefabs/[CameraRig].prefab.

The SteamVR_Unity_Toolkit/Prefabs/[CameraRig] can be dropped into any scene to provide instant access to a VR game camera via the VR headset and tracking of the VR controllers including model representations.

FramesPerSecondCanvas

This canvas adds a frames per second text element to the headset. To use the prefab it must be placed into the scene then the headset camera needs attaching to the canvas:

There are a number of parameters that can be set on the Prefab. Expanding the FramesPerSecondCanvas object in the hierarchy view shows the child FramesPerSecondText obejct and clicking on that reveals additional paramters which can be set via the FramesPerSecondViewer script (which can be found in SteamVR_Unity_Toolkit/Scripts/Helper/FramesPerSecondViewer)

The following script parameters are available:

An example of the FramesPerSecondCanvas Prefab can be viewed in the scene 018_CameraRig_FramesPerSecondCounter which displays the frames per second in the centre of the headset view. Pressing the trigger generates a new sphere and pressing the touchpad generates ten new spheres. Eventually when lots of spheres are present the FPS will drop and demonstrate the prefab.

Scripts

This directory contains all of the toolkit scripts that add VR functionality to Unity.

The current available scripts are:

Controller Actions (SteamVR_ControllerActions)

The Controller Actions script provides helper methods to deal with common controller actions. The following public methods are available:

An example of the SteamVR_ControllerActions script can be viewed in the scene Examples/016_Controller_HapticRumble which demonstrates the ability to hide a controller model and make the controller vibrate for a given length of time at a given intensity.

Controller Events (SteamVR_ControllerEvents)

The Controller Events script is attached to a Controller object within the [CameraRig] prefab and provides event listeners for every button press on the controller (excluding the System Menu button as this cannot be overriden and is always used by Steam).

When a controller button is pressed, the script emits an event to denote that the button has been pressed which allows other scripts to listen for this event without needing to implement any controller logic.

The script also has a public boolean pressed state for the buttons to allow the script to be queried by other scripts to check if a button is being held down.

When a controller button is released, the script also emits an event denoting that the button has been released.

The controller touchpad has two states, it can either be touched where the user simply presses their finger on the pressure sensitive pad or it can be clicked where the user presses down on the pad until it makes a clicking sound.

The Controller Events script deals with both touchpad touch and click events separately.

There are two button axis on the controller:

There are two additional events emitted when either the Touchpad axis or the Trigger axis change their value which can be used to determine the change in either of the axis for finer control such as using the Touchpad to move a character, or knowing the pressure that the trigger is being pressed.

The Touchpad Axis is reported via the TouchpadAxis payload variable which is updated on any Controller Event.

The Trigger Axis is reported via the buttonPressure payload variable which is updated on any Controller Event. Any other button press will report a button pressure of 1 or 0 as all other buttons are digital (they are either clicked or not clicked) but because the Trigger is analog it will report a varying button pressure.

The amount of fidelity in the changes on the axis can be determined by the axisFidelity parameter on the script, which is defaulted to 1. Any number higher than 2 will probably give too sensitive results.

The event payload that is emitted contains:

There are also common action aliases that are emitted when controller buttons are pressed. These action aliases can be mapped to a preferred controller button. The aliases are:

Each of the above aliases can have the preferred controller button mapped to their usage by selecting it from the drop down on the script parameters window.

When the set button is pressed it will emit the actual button event as well as an additional event that the alias is "On". When the set button is released it will emit the actual button event as well as an additional event that the alias button is "Off".

Listening for these alias events rather than the actual button events means it's easier to customise the controller buttons to the actions they should perform.

An example of the SteamVR_ControllerEvents script can be viewed in the scene Examples/002_Controller_Events and code examples of how the events are utilised and listened to can be viewed in the script Examples/Scripts/SteamVR_ControllerEvents_ListenerExample.cs

Simple Laser Pointer (SteamVR_SimplePointer)

The Simple Pointer emits a coloured beam from the end of the controller to simulate a laser beam. It can be useful for pointing to objects within a scene and it can also determine the object it is pointing at and the distance the object is from the controller the beam is being emitted from.

The laser beam is activated by default by pressing the Grip on the controller. The event it is listening for is the AliasPointer events so the pointer toggle button can be set by changing the Pointer Toggle button on the SteamVR_ControllerEvents script parameters.

The Simple Pointer script is attached to a Controller object within the [CameraRig] prefab and the Controller object also requires the SteamVR_ControllerEvents script to be attached as it uses this for listening to the controller button events for enabling and disabling the beam.

The following script parameters are available:

The Simple Pointer object extends the SteamVR_WorldPointer abstract class and therefore emits the same events and payload.

An example of the SteamVR_SimplePointer script can be viewed in the scene Examples/003_Controller_SimplePointer and code examples of how the events are utilised and listened to can be viewed in the script Examples/Scripts/SteamVR_ControllerPointerEvents_ListenerExample.cs

Bezier Curve Laser Pointer (SteamVR_BezierPointer)

The Bezier Pointer emits a curved line (made out of spheres) from the end of the controller to a point on a ground surface (at any height). It is more useful than the Simple Laser Pointer for traversing objects of various heights as the end point can be curved on top of objects that are not visible to the player.

The laser beam is activated by default by pressing the Grip on the controller. The event it is listening for is the AliasPointer events so the pointer toggle button can be set by changing the Pointer Toggle button on the SteamVR_ControllerEvents script parameters.

The Bezier Pointer script is attached to a Controller object within the [CameraRig] prefab and the Controller object also requires the SteamVR_ControllerEvents script to be attached as it uses this for listening to the controller button events for enabling and disabling the beam.

The following script parameters are available:

The Bezier Pointer object extends the SteamVR_WorldPointer abstract class and therefore emits the same events and payload.

An example of the SteamVR_BezierPointer script can be viewed in the scene Examples/009_Controller_BezierPointer which is used in conjunction with the Height Adjust Teleporter shows how it is possible to traverse different height objects using the curved pointer without needing to see the top of the object.

Another example can be viewed in the scene Examples/012_Controller_PointerWithAreaCollision that shows how a Bezier Pointer with the Play Area Cursor and Collision Detection enabled can be used to traverse a game area but not allow teleporting into areas where the walls or other objects would fall into the play area space enabling the player to enter walls.

The bezier curve generation code is in another script located at SteamVR_Unity_Toolkit/Scripts/Helper/CurveGenerator.cs and was heavily inspired by the tutorial and code from Catlike Coding.

Basic Teleporter (SteamVR_BasicTeleport)

The basic teleporter updates the [CameraRig] x/z position in the game world to the position of a World Pointer's tip location which is set via the WorldPointerDestinationSet event. The y position is never altered so the basic teleporter cannot be used to move up and down game objects as it only allows for travel across a flat plane.

The Basic Teleport script is attached to the [CameraRig] prefab and requires an implementation of the WorldPointer script to be attached to another game object (e.g. SteamVR_SimplePointer attached to the Controller object).

The following script parameters are available:

An example of the SteamVR_BasicTeleport script can be viewed in the scene Examples/004_CameraRig_BasicTeleport. The scene uses the SteamVR_SimplePointer script on the Controllers to initiate a laser pointer with the Controller Grip button and when the laser pointer is deactivated (release the Grip) then the player is teleported to the location of the laser pointer tip.

Height Adjustable Teleporter (SteamVR_HeightAdjustTeleport)

The height adjust teleporter extends the basic teleporter and allows for the y position of the [CameraRig] to be altered based on whether the teleport location is on top of another object.

Like the basic teleporter the Height Adjust Teleport script is attached to the [CameraRig] prefab and requires a World Pointer to be available.

The following script parameters are available:

The Play Space Falling option also works in the opposite way that if the player's headset is above an object then the player is teleported automatically on top of that object, which is useful for simulating climbing stairs without needing to use the pointer beam location. If this option is turned off then the player can hover in mid air at the same y position of the object they are standing on.

An example of the SteamVR_HeightAdjustTeleport script can be viewed in the scene Examples/007_CameraRig_HeightAdjustTeleport. The scene has a collection of varying height objects that the player can either walk up and down or use the laser pointer to climb on top of them.

Another example can be viewed in the scene Examples/010_CameraRig_TerrainTeleporting which shows how the teleportation of a player can also traverse terrain colliders.

Another example can be viewed in the scene Examples/020_CameraRig_MeshTeleporting which shows how the teleportation of a player can also traverse mesh colliders.

Fading On Headset Collision (SteamVR_HeadsetCollisionFade)

The purpose of the Headset Collision Fade is to detect when the user's VR headset collides with another game object and fades the screen to a solid colour. This is to deal with a player putting their head into a game object and seeing the inside of the object clipping, which is an undesired effect.

The reasoning behind this is if the player puts their head where it shouldn't be, then fading to a colour (e.g. black) will make the player realise they've done something wrong and they'll probably naturally step backwards.

If using Unity 5.3 or older then the Headset Collision Fade script is attached to the Camera (head) object within the [CameraRig] prefab.

If using Unity 5.4 or newer then the Headset Collision Fade script is attached to the Camera (eye) object within the [CameraRig]->Camera (head) prefab.

The following script parameters are available:

An example of the SteamVR_HeadsetCollisionFade script can be viewed in the scene Examples/011_Camera_HeadSetCollisionFading. The scene has collidable walls around the play area and if the player puts their head into any of the walls then the headset will fade to black.

Interactable Object (SteamVR_InteractableObject)

The Interactable Object script is attached to any game object that is required to be interacted with (e.g. via the controllers).

The following script parameters are available:

######Touch Interactions

######Grab Interactions

######Grab Mechanics

######Use Interactions

The basis of this script is to provide a simple mechanism for identifying objects in the game world that can be grabbed or used but it is expected that this script is the base to be inherited into a script with richer functionality.

An example of the SteamVR_InteractableObject can be viewed in the scene Examples/005_Controller_BasicObjectGrabbing. The scene also uses the SteamVR_InteractTouch and SteamVR_InteractGrab scripts on the controllers to show how an interactable object can be grabbed and snapped to the controller and thrown around the game world.

Another example can be viewed in the scene Examples/013_Controller_UsingAndGrabbingMultipleObjects. The scene shows mutltiple objects that can be grabbed by holding the buttons or grabbed by toggling the button click and also has objects that can have their Using state toggled to show how mutliple items can be turned on at the same time.

Touching Interactable Objects (SteamVR_InteractTouch)

The Interact Touch script is attached to a Controller object within the [CameraRig] prefab.

The following script parameters are available:

The following events are emitted:

The event payload that is emitted contains:

An example of the SteamVR_InteractTouch can be viewed in the scene Examples/005_Controller/BasicObjectGrabbing. The scene demonstrates the highlighting of objects that have the SteamVR_InteractableObject script added to them to show the ability to highlight interactable objects when they are touched by the controllers.

Grabbing Interactable Objects (SteamVR_InteractGrab)

The Interact Grab script is attached to a Controller object within the [CameraRig] prefab and the Controller object requires the SteamVR_ControllerEvents script to be attached as it uses this for listening to the controller button events for grabbing and releasing interactable game objects. It listens for the AliasGrabOn and AliasGrabOff events to determine when an object should be grabbed and should be released.

The Controller object also requires the SteamVR_InteractTouch script to be attached to it as this is used to determine when an interactable object is being touched. Only valid touched objects can be grabbed.

An object can be grabbed if the Controller touches a game object which contains the SteamVR_InteractableObject script and has the flag isGrabbable set to true.

If a valid interactable object is grabbable then pressing the set Grab button on the Controller (default is Trigger) will grab and snap the object to the controller and will not release it until the Grab button is released.

When the Controller Grab button is released, if the interactable game object is grabbable then it will be propelled in the direction and at the velocity the controller was at, which can simulate object throwing.

The interactable objects require a collider to activate the trigger and a rigidbody to pick them up and move them around the game world.

The following script parameters are available:

The following events are emitted:

The event payload that is emitted contains:

An example of the SteamVR_InteractGrab can be viewed in the scene Examples/005_Controller/BasicObjectGrabbing. The scene demonstrates the grabbing of interactable objects that have the SteamVR_InteractableObject script attached to them. The objects can be picked up and thrown around.

More complex examples can be viewed in the scene Examples/013_Controller_UsingAndGrabbingMultipleObjects which demonstrates that each controller can grab and use objects independently and objects can also be toggled to their use state simultaneously. The scene Examples/014_Controller_SnappingObjectsOnGrab demonstrates the different mechanisms for snapping a grabbed object to the controller.

Using Interactable Objects (SteamVR_InteractUse)

The Interact Use script is attached to a Controller object within the [CameraRig] prefab and the Controller object requires the SteamVR_ControllerEvents script to be attached as it uses this for listening to the controller button events for using and stop using interactable game objects. It listens for the AliasUseOn and AliasUseOff events to determine when an object should be used and should stop using.

The Controller object also requires the SteamVR_InteractTouch script to be attached to it as this is used to determine when an interactable object is being touched. Only valid touched objects can be used.

An object can be used if the Controller touches a game object which contains the SteamVR_InteractableObject script and has the flag isUsable set to true.

If a valid interactable object is usable then pressing the set Use button on the Controller (default is Trigger) will call the StartUsing method on the touched interactable object.

The following script parameters are available:

The following events are emitted:

The event payload that is emitted contains:

An example can be viewed in the scene Examples/006_Controller_UsingADoor. Which simulates using a door object to open and close it. It also has a cube on the floor that can be grabbed to show how interactable objects can be usable or grabbable.

Another example can be viewed in the scene Examples/008_Controller_UsingAGrabbedObject which shows that objects can be grabbed with one button and used with another (e.g. firing a gun).

Abstract Classes

To allow for reusablity and object consistency, a collection of abstract classes are provided which can be used to extend into a concrete class providing consistent functionality across many different scripts without needing to duplicate code.

The current abstract classes are available:

SteamVR_WorldPointer

This abstract class provides any game pointer the ability to know the the state of the implemented pointer and emit an event to other scripts in the game world.

The World Pointer also provides a play area cursor to be displayed for all cursors that utilise this class. The play area cursor is a representation of the current calibrated play area space and is useful for visualising the potential new play area space in the game world prior to teleporting. It can also handle collisions with objects on the new play area space and prevent teleporting if there are any collisions with objects at the potential new destination.

The play area collider does not work well with terrains as they are uneven and cause collisions regularly so it is recommended that handling play area collisions is not enabled when using terrains.

The following script parameters are available:

The following events are emitted:

The event payload that is emitted contains:

Examples

This directory contains Unity3d scenes that demonstrate the scripts and prefabs being used in the game world to create desired functionality.

There is also a /Scripts directory within the /Examples directory that contains helper scripts utilised by the example scenes to highlight certain functionality (such as event listeners). These example scripts are not required for real world usage.

The current examples are:

Contributing

I would love to get contributions from you! Follow the instructions below on how to make pull requests. For the full contribution guidelines see the Contribution Document.

Pull requests

  1. Fork the project, clone your fork, and configure the remotes.
  2. Create a new topic branch (from master) to contain your feature, chore, or fix.
  3. Commit your changes in logical units.
  4. Make sure all the example scenes are still working.
  5. Push your topic branch up to your fork.
  6. Open a Pull Request with a clear title and description.

License

Code released under the MIT license.