Integrate OpenXR features
OpenXR is an extensible API that you can extend with new features. To facilitate this within the Unity ecosystem, the Unity OpenXR provider supports a feature extension mechanism.
Important
This section of the OpenXR package documentation is for developers integrating the OpenXR features provided by an XR device. If you are developing an XR application, refer to Feature Management for information about how to enable features provided by the XR packages you have installed in your project. App developers typically don't create features or feature groups.
Examples of what you can do with a custom feature include:
Intercepting OpenXR function calls: To intercept OpenXR function calls, override
OpenXRFeature.HookGetInstanceProcAddrand return a different function pointer. This redirects how OpenXR looks up native functions, allowing you to intercept any call. Implementing an interceptor requires a native plug-in that wraps the original function pointer and returns a replacement. The following example assumes the feature is already registered with an[OpenXRFeature]attribute as described in Create OpenXR features:using System; using System.Runtime.InteropServices; using UnityEngine.XR.OpenXR.Features; public class MyInterceptFeature : OpenXRFeature { const string k_LibraryName = "MyNativePlugin"; protected override IntPtr HookGetInstanceProcAddr(IntPtr func) { // Pass the original xrGetInstanceProcAddr to the native plug-in, // which returns a replacement pointer that intercepts the calls you need. return NativeApi.HookGetInstanceProcAddr(func); } static class NativeApi { [DllImport(k_LibraryName, EntryPoint = "MyPlugin_HookGetInstanceProcAddr")] public static extern IntPtr HookGetInstanceProcAddr(IntPtr func); } }The native plug-in receives the original
xrGetInstanceProcAddr, stores it, and returns a new function pointer. When OpenXR calls through the new pointer to look up a function — for examplexrCreateSession— the native code can return its own implementation instead, then call the original when done.Calling OpenXR functions from a feature: To call an OpenXR function within a feature you first need to retrieve a pointer to the function. To do this use the
OpenXRFeature.xrGetInstanceProcAddrfunction pointer to request a pointer to the function you want to call. UsingOpenXRFeature.xrGetInstanceProcAddrto retrieve the function pointer ensures that any intercepted calls set up by features usingOpenXRFeature.HookGetInstanceProcAddrwill be included.Providing a Unity subsystem implementation:
OpenXRFeatureprovides several XR Loader callbacks where you can manage the lifecycle of Unity subsystems. For an example meshing subsystem feature, refer to theMeshing Subsystem Featuresample.Note
A
UnitySubsystemsManifest.jsonfile is required in order for Unity to discover any subsystems you define. At the moment, there are several restrictions around this file:- It must be only 1 subfolder deep in the project or package.
- The native library it refers to must be only 1-2 subfolders deeper than the
UnitySubsystemsManfiest.jsonfile. - The native library it refers to must be only 1-2 subfolders deeper than the
UnitySubsystemsManifest.jsonfile.
Supporting OpenXR interaction profiles: To support OpenXR interaction profiles that aren't currently supported by the Unity OpenXR settings, you can implement a
OpenXRInteractionFeaturesubclass.Requiring a more recent or custom OpenXR loader library: you can specify that your feature requires a minimum version of the standard OpenXR loader library or that it requires a custom loader library that you supply.
Refer to the following topics for information about implementing OpenXR features:
| Topic | Description |
|---|---|
| Create OpenXR features | How to add features. |
| Define OpenXR feature groups | How to define groups to organize OpenXR features. |
| Create OpenXR interaction features | How to add support for interaction profiles. |
| Require a custom loader library | How to require a custom loader library for features. |