9using System.Collections.Generic;
12#if UNITY_2017_2_OR_NEWER
24 public static class XRSupportUtil {
26 #if UNITY_2019_2_OR_NEWER
27 private static System.Collections.Generic.List<XRNodeState> nodeStates =
28 new System.Collections.Generic.List<XRNodeState>();
31 public static bool IsXREnabled() {
32 #if UNITY_2017_2_OR_NEWER
33 return XRSettings.enabled;
35 return VRSettings.enabled;
39 public static bool IsXRDevicePresent() {
40 #if UNITY_2020_1_OR_NEWER
41 return XRSettings.isDeviceActive;
42 #elif UNITY_2017_2_OR_NEWER
43 return XRDevice.isPresent;
45 return VRDevice.isPresent;
49 static bool outputPresenceWarning =
false;
50 public static bool IsUserPresent(
bool defaultPresence =
true) {
51 #if UNITY_2019_3_OR_NEWER
52 var devices =
new List<InputDevice>();
53 InputDevices.GetDevicesWithCharacteristics(InputDeviceCharacteristics.HeadMounted, devices);
54 if (devices.Count == 0 && !outputPresenceWarning) {
55 Debug.LogWarning(
"No head-mounted devices found. Possibly no HMD is available to the XR system.");
56 outputPresenceWarning =
true;
58 if (devices.Count != 0) {
59 var device = devices[0];
60 if (device.TryGetFeatureValue(CommonUsages.userPresence, out var userPresent)) {
64 #elif UNITY_2017_2_OR_NEWER
65 var userPresence = XRDevice.userPresence;
66 if (userPresence == UserPresenceState.Present) {
68 }
else if (!outputPresenceWarning && userPresence == UserPresenceState.Unsupported) {
69 Debug.LogWarning(
"XR UserPresenceState unsupported (XR support is probably disabled).");
70 outputPresenceWarning =
true;
73 if (!outputPresenceWarning){
74 Debug.LogWarning(
"XR UserPresenceState is only supported in 2017.2 and newer.");
75 outputPresenceWarning =
true;
78 return defaultPresence;
81 public static Vector3 GetXRNodeCenterEyeLocalPosition() {
82 #if UNITY_2019_2_OR_NEWER
83 InputTracking.GetNodeStates(nodeStates);
85 foreach(XRNodeState state
in nodeStates) {
86 if(state.nodeType == XRNode.CenterEye &&
87 state.TryGetPosition(out position))
91 #elif UNITY_2017_2_OR_NEWER
92 return InputTracking.GetLocalPosition(XRNode.CenterEye);
94 return InputTracking.GetLocalPosition(VRNode.CenterEye);
98 public static Quaternion GetXRNodeCenterEyeLocalRotation() {
99 #if UNITY_2019_2_OR_NEWER
100 InputTracking.GetNodeStates(nodeStates);
102 foreach (XRNodeState state
in nodeStates) {
103 if (state.nodeType == XRNode.CenterEye &&
104 state.TryGetRotation(out rotation))
108 #elif UNITY_2017_2_OR_NEWER
109 return InputTracking.GetLocalRotation(XRNode.CenterEye);
111 return InputTracking.GetLocalRotation(VRNode.CenterEye);
115 public static Vector3 GetXRNodeHeadLocalPosition() {
116 #if UNITY_2019_2_OR_NEWER
117 InputTracking.GetNodeStates(nodeStates);
119 foreach(XRNodeState state
in nodeStates) {
120 if(state.nodeType == XRNode.Head &&
121 state.TryGetPosition(out position))
125 #elif UNITY_2017_2_OR_NEWER
126 return InputTracking.GetLocalPosition(XRNode.Head);
128 return InputTracking.GetLocalPosition(VRNode.Head);
132 public static Quaternion GetXRNodeHeadLocalRotation() {
133 #if UNITY_2019_2_OR_NEWER
134 InputTracking.GetNodeStates(nodeStates);
136 foreach (XRNodeState state
in nodeStates) {
137 if (state.nodeType == XRNode.Head &&
138 state.TryGetRotation(out rotation))
142 #elif UNITY_2017_2_OR_NEWER
143 return InputTracking.GetLocalRotation(XRNode.Head);
145 return InputTracking.GetLocalRotation(VRNode.Head);
149 public static Vector3 GetXRNodeLocalPosition(
int node) {
150 #if UNITY_2019_2_OR_NEWER
151 InputTracking.GetNodeStates(nodeStates);
153 foreach(XRNodeState state
in nodeStates) {
154 if(state.nodeType == (XRNode)node &&
155 state.TryGetPosition(out position))
159 #elif UNITY_2017_2_OR_NEWER
160 return InputTracking.GetLocalPosition((XRNode)node);
162 return InputTracking.GetLocalPosition((VRNode)node);
166 public static Quaternion GetXRNodeLocalRotation(
int node) {
167 #if UNITY_2019_2_OR_NEWER
168 InputTracking.GetNodeStates(nodeStates);
170 foreach (XRNodeState state
in nodeStates) {
171 if (state.nodeType == (XRNode)node &&
172 state.TryGetRotation(out rotation))
176 #elif UNITY_2017_2_OR_NEWER
177 return InputTracking.GetLocalRotation((XRNode)node);
179 return InputTracking.GetLocalRotation((VRNode)node);
183 public static void Recenter()
185 var devices =
new List<InputDevice>();
186 InputDevices.GetDevicesWithCharacteristics(InputDeviceCharacteristics.HeadMounted, devices);
187 if (devices.Count == 0)
return;
188 var hmdDevice = devices[0];
190 if(hmdDevice.subsystem !=
null)
191 hmdDevice.subsystem.TryRecenter();
194 public static string GetLoadedDeviceName() {
195 #if UNITY_2017_2_OR_NEWER
196 return XRSettings.loadedDeviceName;
198 return VRSettings.loadedDeviceName;
203 public static bool IsRoomScale() {
204 #if UNITY_2019_3_OR_NEWER
205 var devices =
new List<InputDevice>();
206 InputDevices.GetDevicesWithCharacteristics(InputDeviceCharacteristics.HeadMounted, devices);
207 if (devices.Count == 0)
return false;
208 var hmdDevice = devices[0];
209 if (hmdDevice.subsystem ==
null)
return false;
210#if !UNITY_2020_1_OR_NEWER
211 if(hmdDevice.subsystem !=
null) {
213 return hmdDevice.subsystem.GetTrackingOriginMode().HasFlag(TrackingOriginModeFlags.Floor);
214 #if !UNITY_2020_1_OR_NEWER
216 #pragma warning disable 0618
217 return XRDevice.GetTrackingSpaceType() == TrackingSpaceType.RoomScale;
218 #pragma warning restore 0618
221 #elif UNITY_2017_2_OR_NEWER
222 return XRDevice.GetTrackingSpaceType() == TrackingSpaceType.RoomScale;
224 return VRDevice.GetTrackingSpaceType() == TrackingSpaceType.RoomScale;
228 #if UNITY_2020_1_OR_NEWER
229 static List<Vector3> _boundaryPoints =
new List<Vector3>();
232 public static bool IsLargePlayspace() {
233 #if UNITY_2020_1_OR_NEWER
234 var devices =
new List<InputDevice>();
235 InputDevices.GetDevicesWithCharacteristics(InputDeviceCharacteristics.HeadMounted, devices);
236 if (devices.Count == 0)
return false;
237 var hmdDevice = devices[0];
238 if (hmdDevice.subsystem ==
null)
return false;
239 hmdDevice.subsystem.TryGetBoundaryPoints(_boundaryPoints);
240 Bounds playspaceSize =
new Bounds();
241 foreach(Vector3 boundaryPoint
in _boundaryPoints) { playspaceSize.Encapsulate(boundaryPoint); }
242 return playspaceSize.size.magnitude > 1f;
244 return IsRoomScale();
248 public static float GetGPUTime() {
250 #if UNITY_5_6_OR_NEWER
251 #if UNITY_2017_2_OR_NEWER
252 UnityEngine.XR.XRStats.TryGetGPUTimeLastFrame(out gpuTime);
254 UnityEngine.VR.VRStats.TryGetGPUTimeLastFrame(out gpuTime);