Create new script
Create a folder named Scripts inside Assets. Then create a file named WatchOverlay.cs inside the Scripts folder. We will add our overlay code to this script.
Copy the following code to WatchOverlay.cs.
using UnityEngine;
public class WatchOverlay : MonoBehaviour
{
private void Start()
{
}
}
Put the script to the scene
In the hierarchy window, right click > Create Empty.
Change the object name to WatchOverlay, then drag the WatchOverlay.cs file from the project window to the newly created object.
Add using directive
Add using Valve.VR to WatchOverlay.cs to use the OpenVR API. This namespace is included in the SteamVR Plugin.
using UnityEngine;
+ using Valve.VR;
public class WatchOverlay : MonoBehaviour
{
private void Start()
{
}
}
Initialize OpenVR
Initialize OpenVR with Init() to use the API. (read the wiki for details)
using UnityEngine;
using Valve.VR;
public class WatchOverlay : MonoBehaviour
{
private void Start()
{
+ var error = EVRInitError.None;
+ OpenVR.Init(ref error, EVRApplicationType.VRApplication_Overlay);
}
}
We pass two arguments to Init()
.
The first argument is a reference. If an error occurs during initialization, Init()
sets the variable's value referenced to the error. All errors are defined in EVRInitError.
The second argument is the application type, which will be EVRApplicationType.VRApplication_Overlay
for overlay applications. All application types are defined in EVRApplicationType.
If the application has been initialized as an overlay, it can be run with other VR applications at the same time.
Initialize error handling
Add error handling.
using UnityEngine;
using Valve.VR;
+ using System;
public class WatchOverlay : MonoBehaviour
{
private void Start()
{
var error = EVRInitError.None;
OpenVR.Init(ref error, EVRApplicationType.VRApplication_Overlay);
+ if (error != EVRInitError.None)
+ {
+ throw new Exception("Failed to initialize OpenVR: " + error);
+ }
}
}
If the initialization succeeds, the error value will remain EVRInitError.None
. We will throw an Exception
if this is not the case. Note that you need to add using System
to use Exception
.
If OpenVR is already initialized
If OpenVR has already been initialized, skip the initialization.
using UnityEngine;
using Valve.VR;
using System;
public class WatchOverlay : MonoBehaviour
{
private void Start()
{
+ if (OpenVR.System != null) return;
var error = EVRInitError.None;
OpenVR.Init(ref error, EVRApplicationType.VRApplication_Overlay);
if (error != EVRInitError.None)
{
throw new Exception("Failed to initialize OpenVR: " + error);
}
}
}
If OpenVR has not been initialized, OpenVR.System
is null
.
The API is broken down into parts such as the following. They are null
before initialization.
- OpenVR.System
- OpenVR.Chaperone
- OpenVR.Compositor
- OpenVR.Overlay
- OpenVR.RenderModels
- OpenVR.Screenshots
- OpenVR.Input
Cleanup
Add cleanup to dispose of the initialized OpenVR.
Call Shutdown() at the end of the program. (read the wiki for details)
using UnityEngine;
using Valve.VR;
using System;
public class WatchOverlay : MonoBehaviour
{
private void Start()
{
if (OpenVR.System != null) return;
var error = EVRInitError.None;
OpenVR.Init(ref error, EVRApplicationType.VRApplication_Overlay);
if (error != EVRInitError.None)
{
throw new Exception("Failed to initialize OpenVR: " + error);
}
}
+ private void OnDestroy()
+ {
+ if (OpenVR.System != null)
+ {
+ OpenVR.Shutdown();
+ }
+ }
}
Check the initialization works
Let's access the initialized OpenVR API.
using UnityEngine;
using Valve.VR;
using System;
public class WatchOverlay : MonoBehaviour
{
private void Start()
{
if (OpenVR.System != null) return;
+ Debug.Log(OpenVR.Overlay);
var error = EVRInitError.None;
OpenVR.Init(ref error, EVRApplicationType.VRApplication_Overlay);
if (error != EVRInitError.None)
{
throw new Exception("Failed to initialize OpenVR: " + error);
return;
}
+ Debug.Log(OpenVR.Overlay);
}
private void OnDestroy()
{
if (OpenVR.System != null)
{
OpenVR.Shutdown();
}
}
}
We can see that the API is available after initialization.
If the SteamVR has not launched, it should be automatically launched by Init()
.
Optional: Initialize OpenVR by SteamVR Plugin setting
We don’t use it in this tutorial, but the SteamVR Unity Plugin has an automatic initialization setting.
Check Initialize XR on Project Settings > Startup In XR Plug-in Management.
Select Overlay as the Application Type in the OpenVR setting.
Delete the Debug.Log()
.
private void Start()
{
if (OpenVR.System != null) return;
- Debug.Log(OpenVR.Overlay);
var error = EVRInitError.None;
OpenVR.Init(ref error, EVRApplicationType.VRApplication_Overlay);
if (error != EVRInitError.None)
{
throw new Exception("Failed to initialize OpenVR: " + error);
return;
}
- Debug.Log(OpenVR.Overlay);
}
Organize code
We have initialized and cleaned up OpenVR. Let’s organize the code here.
This tutorial will organize code periodically to keep methods small for clarity.
Initialize
Move the initialization code into InitOpenVR()
.
using UnityEngine;
using Valve.VR;
using System;
public class WatchOverlay : MonoBehaviour
{
private void Start()
{
+ InitOpenVR();
- if (OpenVR.System != null) return;
-
- var error = EVRInitError.None;
- OpenVR.Init(ref error, EVRApplicationType.VRApplication_Overlay);
- if (error != EVRInitError.None)
- {
- throw new Exception("Failed to initialize OpenVR: " + error);
- }
}
private void OnDestroy()
{
if (OpenVR.System != null)
{
OpenVR.Shutdown();
}
}
+ private void InitOpenVR()
+ {
+ if (OpenVR.System != null) return;
+
+ var error = EVRInitError.None;
+ OpenVR.Init(ref error, EVRApplicationType.VRApplication_Overlay);
+ if (error != EVRInitError.None)
+ {
+ throw new Exception("Failed to initialize OpenVR: " + error);
+ }
+ }
}
Optional: If you want to use return
instead of throw
This tutorial uses throw
for readability of error handling. If you prefer return
to return an error code or a bool value, replace the error handling code with the following.
// Return error code
private bool InitOpenVR()
{
if (OpenVR.System != null) return;
var error = EVRInitError.None;
OpenVR.Init(ref error, EVRApplicationType.VRApplication_Overlay);
if (error != EVRInitError.None)
{
Debug.LogError("Failed to initialize OpenVR: " + error);
}
return error;
}
// Return bool value
private bool InitOpenVR()
{
if (OpenVR.System != null) return;
var error = EVRInitError.None;
OpenVR.Init(ref error, EVRApplicationType.VRApplication_Overlay);
if (error != EVRInitError.None)
{
Debug.LogError("Failed to initialize OpenVR: " + error);
return false;
}
return true;
}
Cleanup
Similarly, move the cleanup code to ShutdownOpenVR()
.
using UnityEngine;
using Valve.VR;
using System;
public class WatchOverlay : MonoBehaviour
{
private void Start()
{
InitOpenVR();
}
private void OnDestroy()
{
- if (OpenVR.System != null)
- {
- OpenVR.Shutdown();
- }
+ ShutdownOpenVR();
}
private void InitOpenVR()
{
if (OpenVR.System != null) return;
var error = EVRInitError.None;
OpenVR.Init(ref error, EVRApplicationType.VRApplication_Overlay);
if (error != EVRInitError.None)
{
throw new Exception("Failed to initialize OpenVR: " + error);
}
}
+ private void ShutdownOpenVR()
+ {
+ if (OpenVR.System != null)
+ {
+ OpenVR.Shutdown();
+ }
+ }
}
Final code
using UnityEngine;
using Valve.VR;
using System;
public class WatchOverlay : MonoBehaviour
{
private void Start()
{
InitOpenVR();
}
private void OnDestroy()
{
ShutdownOpenVR();
}
private void InitOpenVR()
{
if (OpenVR.System != null) return;
var error = EVRInitError.None;
OpenVR.Init(ref error, EVRApplicationType.VRApplication_Overlay);
if (error != EVRInitError.None)
{
throw new Exception("Failed to initialize OpenVR: " + error);
}
}
private void ShutdownOpenVR()
{
if (OpenVR.System != null)
{
OpenVR.Shutdown();
}
}
}
Here, we have initialized and cleaned up OpenVR. Now we can access OpenVR APIs like overlay. In the next part, we will create an overlay with this API.
Top comments (0)