version 2.0.0

This commit is contained in:
srl87
2023-09-14 18:17:47 +08:00
parent 13e9d00b37
commit ca21423a06
953 changed files with 125887 additions and 21229 deletions

View File

@@ -0,0 +1,24 @@
using UnityEngine.InputSystem;
namespace UnityEngine.XR.OpenXR.Samples.ControllerSample
{
public class ActionAssetEnabler : MonoBehaviour
{
[SerializeField]
InputActionAsset m_ActionAsset;
public InputActionAsset actionAsset
{
get => m_ActionAsset;
set => m_ActionAsset = value;
}
private void OnEnable()
{
if(m_ActionAsset != null)
{
m_ActionAsset.Enable();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b6292cddb0024284ea1f3c804ace5d87
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,88 @@
using System;
using UnityEngine.InputSystem;
using UnityEngine.UI;
namespace UnityEngine.XR.OpenXR.Samples.ControllerSample
{
public class ActionToButtonISX : MonoBehaviour
{
[SerializeField]
private InputActionReference m_ActionReference;
public InputActionReference actionReference { get => m_ActionReference ; set => m_ActionReference = value; }
[SerializeField]
Color enabledColor = Color.green;
[SerializeField]
Color disabledColor = Color.red;
[SerializeField]
Image image = null;
Graphic graphic = null;
Graphic[] graphics = new Graphic[] { };
private void OnEnable()
{
if (image == null)
Debug.LogWarning("ActionToButton Monobehaviour started without any associated image. This input will not be reported.", this);
graphic = gameObject.GetComponent<Graphic>();
graphics = gameObject.GetComponentsInChildren<Graphic>();
}
Type lastActiveType = null;
void Update()
{
if (actionReference != null && actionReference.action != null && image != null && actionReference.action.enabled && actionReference.action.controls.Count > 0)
{
SetVisible(true);
Type typeToUse = null;
if (actionReference.action.activeControl != null)
{
typeToUse = actionReference.action.activeControl.valueType;
}
else
{
typeToUse = lastActiveType;
}
if(typeToUse == typeof(bool))
{
lastActiveType = typeof(bool);
bool value = actionReference.action.ReadValue<bool>();
image.color = value ? enabledColor : disabledColor;
}
else if(typeToUse == typeof(float))
{
lastActiveType = typeof(float);
float value = actionReference.action.ReadValue<float>();
image.color = value > 0.5 ? enabledColor : disabledColor;
}
else
{
image.color = disabledColor;
}
}
else
{
SetVisible(false);
}
}
void SetVisible(bool visible)
{
if (graphic != null)
graphic.enabled = visible;
for (int i = 0; i < graphics.Length; i++)
{
graphics[i].enabled = visible;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1879fed0e0310334fb310daf7dcc4784
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.XR;
namespace UnityEngine.XR.OpenXR.Samples.ControllerSample
{
public class ActionToHaptics : MonoBehaviour
{
public InputActionReference action;
public float _amplitude = 1.0f;
public float _duration = 0.1f;
private void Start()
{
if (action == null)
return;
action.action.Enable();
action.action.performed += (ctx) =>
{
var control = action.action.activeControl;
if (null == control)
return;
if (control.device is XRControllerWithRumble rumble)
rumble.SendImpulse(_amplitude, _duration);
};
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a71a8cacc8de6e9449396d7cd616b05e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,56 @@
using UnityEngine.UI;
using UnityEngine.InputSystem;
namespace UnityEngine.XR.OpenXR.Samples.ControllerSample
{
public class ActionToSliderISX : MonoBehaviour
{
[SerializeField]
private InputActionReference m_ActionReference;
public InputActionReference actionReference { get => m_ActionReference; set => m_ActionReference = value; }
[SerializeField]
Slider slider = null;
Graphic graphic = null;
Graphic[] graphics = new Graphic[]{ };
private void OnEnable()
{
if (slider == null)
Debug.LogWarning("ActionToSlider Monobehaviour started without any associated slider. This input will not be reported.", this);
graphic = gameObject.GetComponent<Graphic>();
graphics = gameObject.GetComponentsInChildren<Graphic>();
}
void Update()
{
if (actionReference != null && actionReference.action != null && slider != null)
{
if (actionReference.action.enabled)
{
SetVisible(true);
}
float value = actionReference.action.ReadValue<float>();
slider.value = value;
}
else
{
SetVisible(false);
}
}
void SetVisible(bool visible)
{
if (graphic != null)
graphic.enabled = visible;
for (int i = 0; i < graphics.Length; i++)
{
graphics[i].enabled = visible;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 47dc0f697f292694f85e0ea7d8eab70f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,60 @@
using UnityEngine.UI;
using UnityEngine.InputSystem;
namespace UnityEngine.XR.OpenXR.Samples.ControllerSample
{
public class ActionToVector2SliderISX : MonoBehaviour
{
[SerializeField]
private InputActionReference m_ActionReference;
public InputActionReference actionReference { get => m_ActionReference; set => m_ActionReference = value; }
[SerializeField]
public Slider xAxisSlider = null;
[SerializeField]
public Slider yAxisSlider = null;
private void OnEnable()
{
if (xAxisSlider == null)
Debug.LogWarning("ActionToSlider Monobehaviour started without any associated X-axis slider. This input won't be reported.", this);
if (yAxisSlider == null)
Debug.LogWarning("ActionToSlider Monobehaviour started without any associated Y-axis slider. This input won't be reported.", this);
}
void Update()
{
if (actionReference != null && actionReference.action != null && xAxisSlider != null && yAxisSlider != null)
{
if (actionReference.action.enabled)
{
SetVisible(gameObject, true);
}
Vector2 value = actionReference.action.ReadValue<Vector2>();
xAxisSlider.value = value.x;
yAxisSlider.value = value.y;
}
else
{
SetVisible(gameObject, false);
}
}
void SetVisible(GameObject go, bool visible)
{
Graphic graphic = go.GetComponent<Graphic>();
if (graphic != null)
graphic.enabled = visible;
Graphic[] graphics = go.GetComponentsInChildren<Graphic>();
for (int i = 0; i < graphics.Length; i++)
{
graphics[i].enabled = visible;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 68ffad370daf7de4097bcd7cb411838c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,43 @@
using UnityEngine.InputSystem;
namespace UnityEngine.XR.OpenXR.Samples.ControllerSample
{
public class ActionToVisibilityISX : MonoBehaviour
{
[SerializeField]
InputActionProperty m_ActionReference;
public InputActionProperty actionReference { get => m_ActionReference; set => m_ActionReference = value; }
[SerializeField]
GameObject m_TargetGameobject = null;
public GameObject targetGameObject { get => m_TargetGameobject; set => m_TargetGameobject = value; }
private void Start()
{
if (m_ActionReference != null && m_ActionReference.action != null)
m_ActionReference.action.Enable();
}
void Update()
{
if (m_TargetGameobject == null)
return;
if (m_ActionReference != null
&& m_ActionReference.action != null
&& m_ActionReference.action.controls.Count > 0
&& m_ActionReference.action.enabled == true)
{
m_TargetGameobject.SetActive(true);
return;
}
else
{
// No Matching devices:
m_TargetGameobject.SetActive(false);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6a579b9c6142ede44a4a991db9f3f279
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
namespace UnityEngine.XR.OpenXR.Samples.ControllerSample
{
public class AutomaticTrackingModeChanger : MonoBehaviour
{
[SerializeField]
float m_ChangeInterval = 5.0f;
private float m_TimeRemainingTillChange;
static List<XRInputSubsystem> s_InputSubsystems = new List<XRInputSubsystem>();
static List<TrackingOriginModeFlags> s_SupportedTrackingOriginModes = new List<TrackingOriginModeFlags>();
void OnEnable()
{
m_TimeRemainingTillChange = m_ChangeInterval;
}
void Update()
{
m_TimeRemainingTillChange -= Time.deltaTime;
if (m_TimeRemainingTillChange <= 0.0f)
{
List<XRInputSubsystem> inputSubsystems = new List<XRInputSubsystem>();
SubsystemManager.GetInstances(inputSubsystems);
XRInputSubsystem subsystem = inputSubsystems?[0];
if (subsystem != null)
{
UpdateSupportedTrackingOriginModes(subsystem);
SetToNextMode(subsystem);
}
m_TimeRemainingTillChange += m_ChangeInterval;
}
}
void UpdateSupportedTrackingOriginModes(XRInputSubsystem subsystem)
{
TrackingOriginModeFlags supportedOriginModes = subsystem.GetSupportedTrackingOriginModes();
s_SupportedTrackingOriginModes.Clear();
for (int i = 0; i < 31; i++)
{
uint modeToCheck = 1u << i;
if ((modeToCheck & ((UInt32)supportedOriginModes)) != 0)
{
s_SupportedTrackingOriginModes.Add((TrackingOriginModeFlags)modeToCheck);
}
}
}
void SetToNextMode(XRInputSubsystem subsystem)
{
TrackingOriginModeFlags currentOriginMode = subsystem.GetTrackingOriginMode();
for (int i = 0; i < s_SupportedTrackingOriginModes.Count; i++)
{
if (currentOriginMode == s_SupportedTrackingOriginModes[i])
{
int nextModeIndex = (i + 1) % s_SupportedTrackingOriginModes.Count;
subsystem.TrySetTrackingOriginMode(s_SupportedTrackingOriginModes[nextModeIndex]);
break;
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 26406e1caa9c20448866bf7e5e65061d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,68 @@
using UnityEngine.UI;
using UnityEngine.InputSystem;
namespace UnityEngine.XR.OpenXR.Samples.ControllerSample
{
public class DisplayDeviceInfoFromActionISX : MonoBehaviour
{
[SerializeField]
InputActionProperty m_Property;
public InputActionProperty property { get => m_Property; set => m_Property = value; }
[SerializeField]
GameObject m_RootObject = null;
public GameObject rootObject { get { return m_RootObject; } set { m_RootObject = value; } }
[SerializeField]
Text m_TargetText;
public Text targetText { get { return m_TargetText; } set { m_TargetText = value; } }
void OnEnable()
{
if (targetText == null)
Debug.LogWarning("DisplayDeviceInfo Monobehaviour has no Target Text set. No information will be displayed.");
}
void Update()
{
if(m_Property != null && m_Property.action != null && m_Property.action.controls.Count > 0)
{
if (m_RootObject != null)
m_RootObject.SetActive(true);
var device = m_Property.action.controls[0].device;
if (targetText != null)
{
m_TargetText.text = $"{device.name}\n{device.deviceId}\n";
bool useComma = false;
foreach(var usg in device.usages)
{
if (!useComma)
{
useComma = true;
m_TargetText.text += $"{usg}";
}
else
{
m_TargetText.text += $"{usg},";
}
}
}
return;
}
else
{
if (m_RootObject != null)
m_RootObject.SetActive(false);
// No Matching devices:
if (m_TargetText != null)
m_TargetText.text = "<No Device Connected>";
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 750fa446a80705b45a3059b8f87e989a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,161 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.XR;
using VIVE.OpenXR;
namespace UnityEngine.XR.OpenXR.Samples.ControllerSample
{
public class TrackingModeOrigin : MonoBehaviour
{
[SerializeField]
Image m_RecenteredImage = null;
[SerializeField]
Color m_RecenteredOffColor = Color.red;
[SerializeField]
Color m_RecenteredColor = Color.green;
[SerializeField]
float m_RecenteredColorResetTime = 1.0f;
float m_LastRecenteredTime = 0.0f;
[SerializeField]
TrackingOriginModeFlags m_CurrentTrackingOriginMode;
public TrackingOriginModeFlags currentTrackingOriginMode { get { return m_CurrentTrackingOriginMode; } }
[SerializeField]
Text m_CurrentTrackingOriginModeDisplay = null;
[SerializeField]
TrackingOriginModeFlags m_DesiredTrackingOriginMode;
public TrackingOriginModeFlags desiredTrackingOriginMode { get { return m_DesiredTrackingOriginMode; } set { m_DesiredTrackingOriginMode = value; } }
[SerializeField]
TrackingOriginModeFlags m_SupportedTrackingOriginModes;
public TrackingOriginModeFlags supportedTrackingOriginModes { get { return m_SupportedTrackingOriginModes; } }
static List<XRInputSubsystem> s_InputSubsystems = new List<XRInputSubsystem>();
/*private void OnEnable()
{
SubsystemManager.GetInstances(s_InputSubsystems);
for (int i = 0; i < s_InputSubsystems.Count; i++)
{
s_InputSubsystems[i].trackingOriginUpdated += TrackingOriginUpdated;
}
}
private void OnDisable()
{
SubsystemManager.GetInstances(s_InputSubsystems);
for (int i = 0; i < s_InputSubsystems.Count; i++)
{
s_InputSubsystems[i].trackingOriginUpdated -= TrackingOriginUpdated;
}
}
private void TrackingOriginUpdated(XRInputSubsystem obj)
{
Debug.Log("VIVE.OpenXR.Samples.OpenXRInput.TrackingModeOrigin TrackingOriginUpdated() " + obj != null ? obj.ToString() : "");
m_LastRecenteredTime = Time.time;
}*/
public void OnDesiredSelectionChanged(int newValue)
{
desiredTrackingOriginMode = (TrackingOriginModeFlags)(newValue == 0 ? 0 : (1 << (newValue - 1)));
if (desiredTrackingOriginMode == TrackingOriginModeFlags.Device)
{
float value;
if (XR_FB_display_refresh_rate.GetDisplayRefreshRate(out value) == XrResult.XR_SUCCESS)
{
Debug.Log("GetDisplayRefreshRate = " + value);
}
XR_FB_display_refresh_rate.RequestDisplayRefreshRate(90.0f);
}
else if (desiredTrackingOriginMode == TrackingOriginModeFlags.Floor)
{
float value;
UInt32 count;
float[] values = new float[2];
if (XR_FB_display_refresh_rate.GetDisplayRefreshRate(out value) == XrResult.XR_SUCCESS)
{
Debug.Log("GetDisplayRefreshRate = " + value);
}
XR_FB_display_refresh_rate.RequestDisplayRefreshRate(75.0f);
XrResult result = XR_FB_display_refresh_rate.EnumerateDisplayRefreshRates(displayRefreshRateCapacityInput : 0, displayRefreshRateCountOutput:out count, displayRefreshRates: out values[0]);
if (result == XrResult.XR_SUCCESS)
{
Debug.Log("EnumerateDisplayRefreshRates = " + count);
Array.Resize(ref values, (int)count);
result = XR_FB_display_refresh_rate.EnumerateDisplayRefreshRates(displayRefreshRateCapacityInput: count, displayRefreshRateCountOutput: out count, displayRefreshRates: out values[0]);
if (result == XrResult.XR_SUCCESS)
{
for (int i = 0; i < count; i++)
{
Debug.Log("EnumerateDisplayRefreshRates index " + i + " RefreshRates = " + values[i]);
}
}
}
}
}
private void TrackingOriginUpdated(TrackingOriginModeFlags mode)
{
Debug.Log("VIVE.OpenXR.Samples.OpenXRInput.TrackingModeOrigin TrackingOriginUpdated() " + mode);
m_LastRecenteredTime = Time.time;
}
bool userPresence = false;
private void CheckUserPresence()
{
bool presence = ClientInterface.IsUserPresence();
if (userPresence != presence)
{
userPresence = presence;
Debug.Log("VIVE.OpenXR.Samples.OpenXRInput.TrackingModeOrigin CheckUserPresence() userPresence: " + userPresence);
}
}
void Update()
{
CheckUserPresence();
XRInputSubsystem subsystem = null;
SubsystemManager.GetInstances(s_InputSubsystems);
if(s_InputSubsystems.Count > 0)
{
subsystem = s_InputSubsystems[0];
}
m_SupportedTrackingOriginModes = subsystem?.GetSupportedTrackingOriginModes() ?? TrackingOriginModeFlags.Unknown;
if(m_CurrentTrackingOriginMode != m_DesiredTrackingOriginMode && m_DesiredTrackingOriginMode != TrackingOriginModeFlags.Unknown)
{
subsystem?.TrySetTrackingOriginMode(m_DesiredTrackingOriginMode);
}
var currMode = subsystem?.GetTrackingOriginMode() ?? TrackingOriginModeFlags.Unknown;
if (m_CurrentTrackingOriginMode != currMode)
{
m_CurrentTrackingOriginMode = currMode;
TrackingOriginUpdated(m_CurrentTrackingOriginMode);
}
if (m_CurrentTrackingOriginModeDisplay != null)
m_CurrentTrackingOriginModeDisplay.text = m_CurrentTrackingOriginMode.ToString();
if(m_RecenteredImage != null)
{
float lerp = (Time.time - m_LastRecenteredTime) / m_RecenteredColorResetTime;
lerp = Mathf.Clamp(lerp, 0.0f, 1.0f);
m_RecenteredImage.color = Color.Lerp(m_RecenteredColor, m_RecenteredOffColor, lerp);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: abafcbe629b1aa54886e2789b79365f4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d2dcbbf02b93eaf4e939f712f158db7a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,304 @@
// Copyright HTC Corporation All Rights Reserved.
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.XR;
using System.Text;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif
namespace VIVE.OpenXR.Samples.OpenXRInput
{
[RequireComponent(typeof(Text))]
public class ControllerTracking : MonoBehaviour
{
const string LOG_TAG = "VIVE.OpenXR.Sample.OpenXRInput.ControllerTracking ";
StringBuilder m_sb = null;
StringBuilder sb {
get {
if (m_sb == null) { m_sb = new StringBuilder(); }
return m_sb;
}
}
void DEBUG(StringBuilder msg) { Debug.Log(msg); }
[SerializeField]
private bool m_IsLeft = false;
public bool IsLeft { get { return m_IsLeft; } set { m_IsLeft = value; } }
#if ENABLE_INPUT_SYSTEM
[SerializeField]
private bool m_UseInputAction = true;
public bool UseInputAction { get { return m_UseInputAction; } set { m_UseInputAction = value; } }
[SerializeField]
private InputActionReference m_IsTracked = null;
public InputActionReference IsTracked { get { return m_IsTracked; } set { m_IsTracked = value; } }
[SerializeField]
private InputActionReference m_TrackingState = null;
public InputActionReference TrackingState { get { return m_TrackingState; } set { m_TrackingState = value; } }
[SerializeField]
private InputActionReference m_Position = null;
public InputActionReference Position { get { return m_Position; } set { m_Position = value; } }
[SerializeField]
private InputActionReference m_Rotation = null;
public InputActionReference Rotation { get { return m_Rotation; } set { m_Rotation = value; } }
#endif
/// <summary> VIVE Left Controller Characteristics </summary>
public const InputDeviceCharacteristics kControllerLeftCharacteristics = (
InputDeviceCharacteristics.Left |
InputDeviceCharacteristics.TrackedDevice |
InputDeviceCharacteristics.Controller |
InputDeviceCharacteristics.HeldInHand
);
/// <summary> VIVE Right Controller Characteristics </summary>
public const InputDeviceCharacteristics kControllerRightCharacteristics = (
InputDeviceCharacteristics.Right |
InputDeviceCharacteristics.TrackedDevice |
InputDeviceCharacteristics.Controller |
InputDeviceCharacteristics.HeldInHand
);
private List<UnityEngine.XR.InputDevice> m_InputDevices = new List<UnityEngine.XR.InputDevice>();
private bool GetIsTracked(out bool isTracked, out string msg)
{
isTracked = false;
msg = "No Device";
InputDevices.GetDevices(m_InputDevices);
foreach (UnityEngine.XR.InputDevice id in m_InputDevices)
{
// The device is connected.
if (id.characteristics.Equals((m_IsLeft ? kControllerLeftCharacteristics : kControllerRightCharacteristics)))
{
if (id.TryGetFeatureValue(UnityEngine.XR.CommonUsages.isTracked, out bool value))
{
isTracked = value;
return true;
}
else
{
msg = "Get CommonUsages.isTracked failed.";
}
}
else
{
msg = (m_IsLeft ? "No Left Controller" : "No Right Controller");
}
}
return false;
}
private bool GetTrackingState(out InputTrackingState trackingState, out string msg)
{
trackingState = InputTrackingState.None;
msg = "No Device";
InputDevices.GetDevices(m_InputDevices);
foreach (UnityEngine.XR.InputDevice id in m_InputDevices)
{
// The device is connected.
if (id.characteristics.Equals((m_IsLeft ? kControllerLeftCharacteristics : kControllerRightCharacteristics)))
{
if (id.TryGetFeatureValue(UnityEngine.XR.CommonUsages.trackingState, out InputTrackingState value))
{
trackingState = value;
return true;
}
else
{
msg = "Get CommonUsages.trackingState failed.";
}
}
else
{
msg = (m_IsLeft ? "No Left Controller" : "No Right Controller");
}
}
return false;
}
private bool GetPosition(out Vector3 position, out string msg)
{
position = Vector3.zero;
msg = "No Device";
InputDevices.GetDevices(m_InputDevices);
foreach (UnityEngine.XR.InputDevice id in m_InputDevices)
{
// The device is connected.
if (id.characteristics.Equals((m_IsLeft ? kControllerLeftCharacteristics : kControllerRightCharacteristics)))
{
if (id.TryGetFeatureValue(UnityEngine.XR.CommonUsages.devicePosition, out Vector3 value))
{
position = value;
return true;
}
else
{
msg = "Get CommonUsages.devicePosition failed.";
}
}
else
{
msg = (m_IsLeft ? "No Left Controller" : "No Right Controller");
}
}
return false;
}
private bool GetRotation(out Quaternion rotation, out string msg)
{
rotation = Quaternion.identity;
msg = "No Device";
InputDevices.GetDevices(m_InputDevices);
foreach (UnityEngine.XR.InputDevice id in m_InputDevices)
{
// The device is connected.
if (id.characteristics.Equals((m_IsLeft ? kControllerLeftCharacteristics : kControllerRightCharacteristics)))
{
if (id.TryGetFeatureValue(UnityEngine.XR.CommonUsages.deviceRotation, out Quaternion value))
{
rotation = value;
return true;
}
else
{
msg = "Get CommonUsages.deviceRotation failed.";
}
}
else
{
msg = (m_IsLeft ? "No Left Controller" : "No Right Controller");
}
}
return false;
}
private Text m_Text = null;
private void Start()
{
m_Text = GetComponent<Text>();
}
void Update()
{
if (m_Text == null) { return; }
m_Text.text = (m_IsLeft ? "Left Controller: " : "Right Controller: ");
#if ENABLE_INPUT_SYSTEM
if (m_UseInputAction)
{
m_Text.text += "isTracked: ";
{
if (Utils.GetButton(m_IsTracked, out bool value, out string msg))
{
m_Text.text += value;
}
else
{
m_Text.text += msg;
}
}
m_Text.text += "\n";
m_Text.text += "trackingState: ";
{
if (Utils.GetInteger(m_TrackingState, out InputTrackingState value, out string msg))
{
m_Text.text += value;
}
else
{
m_Text.text += msg;
}
}
m_Text.text += "\n";
m_Text.text += "position (";
{
if (Utils.GetVector3(m_Position, out Vector3 value, out string msg))
{
m_Text.text += value.x.ToString() + ", " + value.y.ToString() + ", " + value.z.ToString();
}
else
{
m_Text.text += msg;
}
}
m_Text.text += ")\n";
m_Text.text += "rotation (";
{
if (Utils.GetQuaternion(m_Rotation, out Quaternion value, out string msg))
{
m_Text.text += value.x.ToString() + ", " + value.y.ToString() + ", " + value.z.ToString() + ", " + value.w.ToString();
}
else
{
m_Text.text += msg;
}
}
m_Text.text += ")";
}
else
#endif
{
m_Text.text += "isTracked: ";
{
if (GetIsTracked(out bool isTracked, out string msg))
{
m_Text.text += isTracked;
}
else
{
m_Text.text += msg;
}
}
m_Text.text += "\n";
m_Text.text += "trackingState: ";
{
if (GetTrackingState(out InputTrackingState trackingState, out string msg))
{
m_Text.text += trackingState;
}
else
{
m_Text.text += msg;
}
}
m_Text.text += "\n";
m_Text.text += "position (";
{
if (GetPosition(out Vector3 position, out string msg))
{
m_Text.text += position.x.ToString() + ", " + position.y.ToString() + ", " + position.z.ToString();
}
else
{
m_Text.text += msg;
}
}
m_Text.text += ")\n";
m_Text.text += "rotation (";
{
if (GetRotation(out Quaternion rotation, out string msg))
{
m_Text.text += rotation.x.ToString() + ", " + rotation.y.ToString() + ", " + rotation.z.ToString() + ", " + rotation.w.ToString();
}
else
{
m_Text.text += msg;
}
}
m_Text.text += ")";
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 48c4f2fcc5f5d8c4190d0fcff62a46c1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,167 @@
// Copyright HTC Corporation All Rights Reserved.
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;
using UnityEngine.XR;
namespace VIVE.OpenXR.Samples.OpenXRInput
{
[RequireComponent(typeof(Text))]
public class EyeDataText : MonoBehaviour
{
const string LOG_TAG = "VIVE.OpenXR.Samples.OpenXRInput.EyeDataText";
void DEBUG(string msg) { Debug.Log(LOG_TAG + " " + msg); }
void INTERVAL(string msg) { if (printIntervalLog) { DEBUG(msg); } }
[SerializeField]
private InputActionReference m_EyePose = null;
public InputActionReference EyePose { get => m_EyePose; set => m_EyePose = value; }
bool getTracked(InputActionReference actionReference)
{
bool tracked = false;
if (OpenXRHelper.VALIDATE(actionReference, out string value))
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.InputSystem.XR.PoseState))
#else
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.XR.OpenXR.Input.Pose))
#endif
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
tracked = actionReference.action.ReadValue<UnityEngine.InputSystem.XR.PoseState>().isTracked;
#else
tracked = actionReference.action.ReadValue<UnityEngine.XR.OpenXR.Input.Pose>().isTracked;
#endif
INTERVAL("getTracked(" + tracked + ")");
}
}
else
{
INTERVAL("getTracked() invalid input: " + value);
}
return tracked;
}
InputTrackingState getTrackingState(InputActionReference actionReference)
{
InputTrackingState state = InputTrackingState.None;
if (OpenXRHelper.VALIDATE(actionReference, out string value))
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.InputSystem.XR.PoseState))
#else
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.XR.OpenXR.Input.Pose))
#endif
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
state = actionReference.action.ReadValue<UnityEngine.InputSystem.XR.PoseState>().trackingState;
#else
state = actionReference.action.ReadValue<UnityEngine.XR.OpenXR.Input.Pose>().trackingState;
#endif
INTERVAL("getTrackingState(" + state + ")");
}
}
else
{
INTERVAL("getTrackingState() invalid input: " + value);
}
return state;
}
Vector3 getPosition(InputActionReference actionReference)
{
var position = Vector3.zero;
if (OpenXRHelper.VALIDATE(actionReference, out string value))
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.InputSystem.XR.PoseState))
#else
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.XR.OpenXR.Input.Pose))
#endif
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
position = actionReference.action.ReadValue<UnityEngine.InputSystem.XR.PoseState>().position;
#else
position = actionReference.action.ReadValue<UnityEngine.XR.OpenXR.Input.Pose>().position;
#endif
INTERVAL("getPosition(" + position.x.ToString() + ", " + position.y.ToString() + ", " + position.z.ToString() + ")");
}
}
else
{
INTERVAL("getPosition() invalid input: " + value);
}
return position;
}
Quaternion getRotation(InputActionReference actionReference)
{
var rotation = Quaternion.identity;
if (OpenXRHelper.VALIDATE(actionReference, out string value))
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.InputSystem.XR.PoseState))
#else
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.XR.OpenXR.Input.Pose))
#endif
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
rotation = actionReference.action.ReadValue<UnityEngine.InputSystem.XR.PoseState>().rotation;
#else
rotation = actionReference.action.ReadValue<UnityEngine.XR.OpenXR.Input.Pose>().rotation;
#endif
INTERVAL("getRotation(" + rotation.x.ToString() + ", " + rotation.y.ToString() + ", " + rotation.z.ToString() + ", " + rotation.w.ToString() + ")");
}
}
else
{
INTERVAL("getRotation() invalid input: " + value);
}
return rotation;
}
private Text m_Text = null;
private void Awake()
{
m_Text = GetComponent<Text>();
}
int printFrame = 0;
private bool printIntervalLog = false;
private void Update()
{
printFrame++;
printFrame %= 300;
printIntervalLog = (printFrame == 0);
if (m_Text == null) { return; }
m_Text.text = "Eye ";
bool tracked = getTracked(m_EyePose);
m_Text.text += "tracked: " + tracked + "\n";
InputTrackingState trackingState = getTrackingState(m_EyePose);
m_Text.text += "tracking state: " + trackingState + "\n";
Vector3 position = getPosition(m_EyePose);
m_Text.text += "position (" + position.x.ToString() + ", " + position.y.ToString() + ", " + position.z.ToString() + ")\n";
m_Text.text += "refresh rate: " + GetRefreshRate().ToString();
}
private float GetRefreshRate()
{
if (XR_FB_display_refresh_rate.GetDisplayRefreshRate(out float rate) == XrResult.XR_SUCCESS) { return rate; }
return 0;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1b67ab3747614ae46ab3c4b7f63907d9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,191 @@
// Copyright HTC Corporation All Rights Reserved.
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.XR;
using System.Text;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif
namespace VIVE.OpenXR.Samples.OpenXRInput
{
[RequireComponent(typeof(Text))]
public class HandInteractionTracking : MonoBehaviour
{
const string LOG_TAG = "VIVE.OpenXR.Sample.OpenXRInput.HandInteractionTracking ";
StringBuilder m_sb = null;
StringBuilder sb {
get {
if (m_sb == null) { m_sb = new StringBuilder(); }
return m_sb;
}
}
void DEBUG(StringBuilder msg) { Debug.Log(msg); }
[SerializeField]
private bool m_IsLeft = false;
public bool IsLeft { get { return m_IsLeft; } set { m_IsLeft = value; } }
#if ENABLE_INPUT_SYSTEM
[SerializeField]
private InputActionReference m_IsTracked = null;
public InputActionReference IsTracked { get { return m_IsTracked; } set { m_IsTracked = value; } }
[SerializeField]
private InputActionReference m_TrackingState = null;
public InputActionReference TrackingState { get { return m_TrackingState; } set { m_TrackingState = value; } }
[SerializeField]
private InputActionReference m_Position = null;
public InputActionReference Position { get { return m_Position; } set { m_Position = value; } }
[SerializeField]
private InputActionReference m_Rotation = null;
public InputActionReference Rotation { get { return m_Rotation; } set { m_Rotation = value; } }
[SerializeField]
private InputActionReference m_Strength = null;
public InputActionReference Strength { get { return m_Strength; } set { m_Strength = value; } }
[SerializeField]
private InputActionReference m_AimPose = null;
public InputActionReference AimPose { get { return m_AimPose; } set { m_AimPose = value; } }
[SerializeField]
private InputActionReference m_SelectValue = null;
public InputActionReference SelectValue { get { return m_SelectValue; } set { m_SelectValue = value; } }
#endif
private Text m_Text = null;
private void Start()
{
m_Text = GetComponent<Text>();
}
void Update()
{
if (m_Text == null) { return; }
m_Text.text = (m_IsLeft ? "Left Grip: " : "Right Grip: ");
#if ENABLE_INPUT_SYSTEM
m_Text.text += "\nisTracked: ";
{
if (Utils.GetButton(m_IsTracked, out bool value, out string msg))
{
m_Text.text += value;
}
else
{
m_Text.text += msg;
}
}
m_Text.text += "\ntrackingState: ";
{
if (Utils.GetInteger(m_TrackingState, out InputTrackingState value, out string msg))
{
m_Text.text += value;
}
else
{
m_Text.text += msg;
}
}
m_Text.text += "\nposition (";
{
if (Utils.GetVector3(m_Position, out Vector3 value, out string msg))
{
m_Text.text += value.x.ToString() + ", " + value.y.ToString() + ", " + value.z.ToString();
}
else
{
m_Text.text += msg;
}
}
m_Text.text += ")\nrotation (";
{
if (Utils.GetQuaternion(m_Rotation, out Quaternion value, out string msg))
{
m_Text.text += value.x.ToString() + ", " + value.y.ToString() + ", " + value.z.ToString() + ", " + value.w.ToString();
}
else
{
m_Text.text += msg;
}
}
m_Text.text += ")\nstrength: ";
{
if (Utils.GetAnalog(m_Strength, out float value, out string msg))
{
m_Text.text += value.ToString();
}
else
{
m_Text.text += msg;
}
}
m_Text.text += "\n";
#endif
m_Text.text += (m_IsLeft ? "Left Aim: " : "Right Aim: ");
#if ENABLE_INPUT_SYSTEM
m_Text.text += "\nisTracked: ";
{
if (Utils.GetPoseIsTracked(m_AimPose, out bool value, out string msg))
{
m_Text.text += value;
}
else
{
m_Text.text += msg;
}
}
m_Text.text += "\ntrackingState: ";
{
if (Utils.GetPoseTrackingState(m_AimPose, out InputTrackingState value, out string msg))
{
m_Text.text += value;
}
else
{
m_Text.text += msg;
}
}
m_Text.text += "\nposition (";
{
if (Utils.GetPosePosition(m_AimPose, out Vector3 value, out string msg))
{
m_Text.text += value.x.ToString() + ", " + value.y.ToString() + ", " + value.z.ToString();
}
else
{
m_Text.text += msg;
}
}
m_Text.text += ")\nrotation (";
{
if (Utils.GetPoseRotation(m_AimPose, out Quaternion value, out string msg))
{
m_Text.text += value.x.ToString() + ", " + value.y.ToString() + ", " + value.z.ToString() + ", " + value.w.ToString();
}
else
{
m_Text.text += msg;
}
}
m_Text.text += ")\n";
m_Text.text += "select: ";
{
if (Utils.GetAnalog(m_SelectValue, out float value, out string msg))
{
m_Text.text += value;
}
else
{
m_Text.text += msg;
}
}
#endif
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8cc9930209b1a084d8d9e102d48a88a5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,34 @@
// Copyright HTC Corporation All Rights Reserved.
using UnityEngine;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif
namespace VIVE.OpenXR.Samples.OpenXRInput
{
public class PoseDriver : MonoBehaviour
{
#if ENABLE_INPUT_SYSTEM
[SerializeField]
private InputActionReference m_DevicePose = null;
public InputActionReference DevicePose { get { return m_DevicePose; } set { m_DevicePose = value; } }
#endif
private void Update()
{
if (m_DevicePose == null) { return; }
string msg = "";
if (Utils.GetPosePosition(m_DevicePose, out Vector3 pos, out msg))
{
transform.localPosition = pos;
}
if (Utils.GetPoseRotation(m_DevicePose, out Quaternion rot, out msg))
{
transform.localRotation = rot;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b864e7d459cda4242abc2881903cf71d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,195 @@
// Copyright HTC Corporation All Rights Reserved.
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.OpenXR;
using VIVE.OpenXR;
using VIVE.OpenXR.Hand;
namespace VIVE.OpenXR.Samples.OpenXRInput
{
public class RenderHand : MonoBehaviour
{
const string LOG_TAG = "VIVE.OpenXR.Samples.Hand.Tracking.RenderHand";
void DEBUG(string msg) { Debug.Log(LOG_TAG + (isLeft ? "Left" : "Right") + ", " + msg); }
void INTERVAL(string msg) { if (printIntervalLog) { DEBUG(msg); } }
// Links between keypoints, 2*i & 2*i+1 forms a link.
// keypoint index: 1: palm, 2-5: thumb, 6-10: index, 11-15: middle, 16-20: ring, 21-25: pinky
// fingers are counted from bottom to top
private static int[] Connections = new int[] {
1, 2, 1, 6, 1, 11, 1, 16, 1, 21, // palm and finger starts
3, 6, 6, 11, 11, 16, 16, 21, // finger starts
2, 3, 3, 4, 4, 5, // thumb
6, 7, 7, 8, 8, 9, 9, 10, // index
11, 12, 12, 13, 13, 14, 14, 15, // middle
16, 17, 17, 18, 18, 19, 19, 20, // ring
21, 22, 22, 23, 23, 24, 24, 25 // pinky
};
[Tooltip("Draw left hand if true, right hand otherwise")]
public bool isLeft = false;
[Tooltip("Use inferred or last-known posed when hand loses tracking if true.")]
public bool allowUntrackedPose = false;
[Tooltip("Default color of hand points")]
public Color pointColor = Color.green;
[Tooltip("Default color of links between keypoints in skeleton mode")]
public Color linkColor = Color.white;
[Tooltip("Material for hand points and links")]
[SerializeField]
private Material material = null;
private List<GameObject> points = new List<GameObject>();
// list of links created (only for skeleton)
private List<GameObject> links = new List<GameObject>();
// Start is called before the first frame update
private XrHandJointLocationEXT[] HandjointLocations = new XrHandJointLocationEXT[(int)XrHandJointEXT.XR_HAND_JOINT_MAX_ENUM_EXT];
// shared material for all point objects
private Material pointMat = null;
// shared material for all link objects
private Material linkMat = null;
private void Start()
{
pointMat = new Material(material);
if (isLeft)
{
pointColor = Color.blue;
}
else
{
pointColor = Color.red;
}
pointMat.color = pointColor;
linkMat = new Material(material);
linkMat.color = linkColor;
for (int i = 0; i < (int)XrHandJointEXT.XR_HAND_JOINT_MAX_ENUM_EXT; i++)
{
var go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
go.name = ((XrHandJointEXT)i).ToString();
go.transform.parent = transform;
go.transform.localScale = Vector3.one * 0.012f;
go.SetActive(false);
points.Add(go);
go.transform.position = new Vector3((float)i * 0.1f, 0, 0);
// handle layer
go.layer = gameObject.layer;
// handle material
go.GetComponent<Renderer>().sharedMaterial = pointMat;
}
// create game objects for links between keypoints, only used in skeleton mode
for (int i = 0; i < Connections.Length; i += 2)
{
var go = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
go.name = "link" + i;
go.transform.parent = transform;
go.transform.localScale = Vector3.one * 0.005f;
go.SetActive(false);
links.Add(go);
// handle layer
go.layer = gameObject.layer;
// handle material
go.GetComponent<Renderer>().sharedMaterial = linkMat;
}
}
int printFrame = 0;
private bool printIntervalLog = false;
private void Update()
{
printFrame++;
printFrame %= 300;
printIntervalLog = (printFrame == 0);
var feature = OpenXRSettings.Instance.GetFeature<ViveHandTracking>();
if (feature && feature.GetJointLocations(isLeft, out HandjointLocations))
{
UpdateJointLocation();
}
else
{
for (int i = 0; i < points.Count; i++)
{
var go = points[i];
go.SetActive(false);
}
for (int i = 0; i < links.Count; i++)
{
var link = links[i];
link.SetActive(false);
}
}
}
public void UpdateJointLocation()
{
for (int i = 0; i < points.Count; i++)
{
var go = points[i];
XrQuaternionf orientation;
XrVector3f position;
go.GetComponent<SphereCollider>().radius = HandjointLocations[i].radius;
INTERVAL(go.name + " radius: " + go.GetComponent<SphereCollider>().radius);
if (allowUntrackedPose) //Use inferred or last-known pose when lost tracking
{
orientation = HandjointLocations[i].pose.orientation;
position = HandjointLocations[i].pose.position;
go.transform.localPosition = position.ToUnityVector();//new Vector3(position.x, position.y, -position.z);
go.SetActive(true);
}
else
{
if ((HandjointLocations[i].locationFlags & XrSpaceLocationFlags.XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT) != 0)
{
orientation = HandjointLocations[i].pose.orientation;
}
if ((HandjointLocations[i].locationFlags & XrSpaceLocationFlags.XR_SPACE_LOCATION_POSITION_TRACKED_BIT) != 0)
{
position = HandjointLocations[i].pose.position;
go.transform.localPosition = new Vector3(position.x, position.y, -position.z);
go.SetActive(true);
}
else
{
INTERVAL("Lost tracking");
go.SetActive(false);
}
/*if (i == 1 && isLeft)
{
DEBUG("points[1]: " + go.name + " active? " + go.activeSelf
+ ", locationFlags: " + HandjointLocations[i].locationFlags
+ ", position (" + go.transform.localPosition.x.ToString() + ", " + go.transform.localPosition.y.ToString() + ", " + go.transform.localPosition.z.ToString() + ")"
+ ", Camera (" + Camera.main.gameObject.transform.localPosition.x.ToString() + ", " + Camera.main.gameObject.transform.localPosition.y.ToString() + ", " + Camera.main.gameObject.transform.localPosition.z.ToString() + ")");
}*/
}
}
for (int i = 0; i < links.Count; i++)
{
var link = links[i];
if (!points[Connections[i * 2]].activeSelf || !points[Connections[i * 2 + 1]].activeSelf)
{
link.SetActive(false);
continue;
}
var pose1 = points[Connections[i * 2]].transform.position;
var pose2 = points[Connections[i * 2 + 1]].transform.position;
// calculate link position and rotation based on points on both end
link.SetActive(true);
link.transform.position = (pose1 + pose2) / 2;
var direction = pose2 - pose1;
link.transform.rotation = Quaternion.FromToRotation(Vector3.up, direction);
link.transform.localScale = new Vector3(0.006f, direction.magnitude / 2f - 0.0051f, 0.006f);
}
}
public void OnDestroy()
{
DEBUG("OnDestroy");
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c232203bf3067944e84cf70b2629999a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,187 @@
// Copyright HTC Corporation All Rights Reserved.
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.XR;
namespace VIVE.OpenXR.Samples.OpenXRInput
{
public class TrackerPose : MonoBehaviour
{
const string LOG_TAG = "VIVE.OpenXR.Samples.OpenXRInput.TrackerPose";
void DEBUG(string msg) { Debug.Log(LOG_TAG + " " + (IsLeft ? "Left" : "Right") + ", " + msg); }
void INTERVAL(string msg) { if (printIntervalLog) { DEBUG(msg); } }
#region Inspector
public bool IsLeft = false;
[SerializeField]
private InputActionReference m_DevicePose = null;
public InputActionReference DevicePose { get { return m_DevicePose; } set { m_DevicePose = value; } }
bool getDeviceTracked(InputActionReference actionReference)
{
bool tracked = false;
if (OpenXRHelper.VALIDATE(actionReference, out string value))
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.InputSystem.XR.PoseState))
#else
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.XR.OpenXR.Input.Pose))
#endif
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
tracked = actionReference.action.ReadValue<UnityEngine.InputSystem.XR.PoseState>().isTracked;
#else
tracked = actionReference.action.ReadValue<UnityEngine.XR.OpenXR.Input.Pose>().isTracked;
#endif
INTERVAL("getDeviceTracked(" + tracked + ")");
}
}
else
{
INTERVAL("getDeviceTracked() invalid input: " + value);
}
return tracked;
}
InputTrackingState getDeviceTrackingState(InputActionReference actionReference)
{
InputTrackingState state = InputTrackingState.None;
if (OpenXRHelper.VALIDATE(actionReference, out string value))
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.InputSystem.XR.PoseState))
#else
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.XR.OpenXR.Input.Pose))
#endif
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
state = actionReference.action.ReadValue<UnityEngine.InputSystem.XR.PoseState>().trackingState;
#else
state = actionReference.action.ReadValue<UnityEngine.XR.OpenXR.Input.Pose>().trackingState;
#endif
INTERVAL("getDeviceTrackingState(" + state + ")");
}
}
else
{
INTERVAL("getDeviceTrackingState() invalid input: " + value);
}
return state;
}
Vector3 getDevicePosition(InputActionReference actionReference)
{
var position = Vector3.zero;
if (OpenXRHelper.VALIDATE(actionReference, out string value))
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.InputSystem.XR.PoseState))
#else
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.XR.OpenXR.Input.Pose))
#endif
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
position = actionReference.action.ReadValue<UnityEngine.InputSystem.XR.PoseState>().position;
#else
position = actionReference.action.ReadValue<UnityEngine.XR.OpenXR.Input.Pose>().position;
#endif
INTERVAL("getDevicePosition(" + position.x.ToString() + ", " + position.y.ToString() + ", " + position.z.ToString() + ")");
}
}
else
{
INTERVAL("getDevicePosition() invalid input: " + value);
}
return position;
}
Quaternion getDeviceRotation(InputActionReference actionReference)
{
var rotation = Quaternion.identity;
if (OpenXRHelper.VALIDATE(actionReference, out string value))
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.InputSystem.XR.PoseState))
#else
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.XR.OpenXR.Input.Pose))
#endif
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
rotation = actionReference.action.ReadValue<UnityEngine.InputSystem.XR.PoseState>().rotation;
#else
rotation = actionReference.action.ReadValue<UnityEngine.XR.OpenXR.Input.Pose>().rotation;
#endif
INTERVAL("getDeviceRotation(" + rotation.x.ToString() + ", " + rotation.y.ToString() + ", " + rotation.z.ToString() + ", " + rotation.w.ToString() + ")");
}
}
else
{
INTERVAL("getDeviceRotation() invalid input: " + value);
}
return rotation;
}
[SerializeField]
private InputActionReference m_PrimaryButton = null;
public InputActionReference PrimaryButton { get { return m_PrimaryButton; } set { m_PrimaryButton = value; } }
[SerializeField]
private InputActionReference m_Menu = null;
public InputActionReference Menu { get { return m_Menu; } set { m_Menu = value; } }
bool getButton(InputActionReference actionReference)
{
bool pressed = false;
if (OpenXRHelper.VALIDATE(actionReference, out string value))
{
if (actionReference.action.activeControl.valueType == typeof(bool))
pressed = actionReference.action.ReadValue<bool>();
if (actionReference.action.activeControl.valueType == typeof(float))
pressed = actionReference.action.ReadValue<float>() > 0;
}
else
{
INTERVAL("getButton() invalid input: " + value);
}
return pressed;
}
#endregion
int printFrame = 0;
protected bool printIntervalLog = false;
private void Update()
{
printFrame++;
printFrame %= 300;
printIntervalLog = (printFrame == 0);
var tracked = getDeviceTracked(m_DevicePose);
var trackingState = getDeviceTrackingState(m_DevicePose);
var position = getDevicePosition(m_DevicePose);
var rotation = getDeviceRotation(m_DevicePose);
if (getButton(m_PrimaryButton))
DEBUG("Update() " + m_PrimaryButton.name + " is pressed.");
if (getButton(m_Menu))
DEBUG("Update() " + m_Menu.name + " is pressed.");
if (tracked)
{
transform.localPosition = position;
transform.localRotation = rotation;
}
else
{
if (printIntervalLog)
DEBUG("Update() Tracker is not tracked.");
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4c129ad20f238874c92d1c11fa0f80e8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,123 @@
// Copyright HTC Corporation All Rights Reserved.
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;
using UnityEngine.XR;
namespace VIVE.OpenXR.Samples.OpenXRInput
{
[RequireComponent(typeof(Text))]
public class TrackerText : MonoBehaviour
{
const string LOG_TAG = "VIVE.OpenXR.Samples.OpenXRInput.TrackerText";
void DEBUG(string msg) { Debug.Log(LOG_TAG + msg); }
#region Right Tracker
[SerializeField]
private InputActionReference m_TrackedR = null;
public InputActionReference TrackedR { get => m_TrackedR; set => m_TrackedR = value; }
[SerializeField]
private InputActionReference m_TrackingStateR = null;
public InputActionReference TrackingStateR { get => m_TrackingStateR; set => m_TrackingStateR = value; }
[SerializeField]
private InputActionReference m_RightA = null;
public InputActionReference RightA { get => m_RightA; set => m_RightA = value; }
#endregion
#region Left Tracker
[SerializeField]
private InputActionReference m_TrackedL = null;
public InputActionReference TrackedL { get => m_TrackedL; set => m_TrackedL = value; }
[SerializeField]
private InputActionReference m_TrackingStateL = null;
public InputActionReference TrackingStateL { get => m_TrackingStateL; set => m_TrackingStateL = value; }
[SerializeField]
private InputActionReference m_LeftX = null;
public InputActionReference LeftX { get => m_LeftX; set => m_LeftX = value; }
[SerializeField]
private InputActionReference m_LeftMenu = null;
public InputActionReference LeftMenu { get => m_LeftMenu; set => m_LeftMenu = value; }
#endregion
private Text m_Text = null;
private void Start()
{
m_Text = GetComponent<Text>();
}
private void Update()
{
if (m_Text == null) { return; }
// Left tracker text
m_Text.text = "Left Tracker ";
{ // Tracked
if (Utils.GetButton(m_TrackedL, out bool value, out string msg))
{
m_Text.text += "tracked: " + value + ", ";
}
}
{ // trackingState
if (Utils.GetInteger(m_TrackingStateL, out InputTrackingState value, out string msg))
{
m_Text.text += "state: " + value + ", ";
}
}
{ // Left X
if (Utils.GetButton(m_LeftX, out bool value, out string msg))
{
if (value)
{
DEBUG("Update() Left X is pressed.");
m_Text.text += "Left X";
}
}
}
{ // Left Menu
if (Utils.GetButton(m_LeftMenu, out bool value, out string msg))
{
if (value)
{
DEBUG("Update() Left Menu is pressed.");
m_Text.text += "Left Menu";
}
}
}
// Right tracker text
m_Text.text += "\nRight Tracker ";
{ // Tracked
if (Utils.GetButton(m_TrackedR, out bool value, out string msg))
{
m_Text.text += "tracked: " + value + ", ";
}
}
{ // trackingState
if (Utils.GetInteger(m_TrackingStateR, out InputTrackingState value, out string msg))
{
m_Text.text += "state: " + value + ", ";
}
}
{ // Right A
if (Utils.GetButton(m_RightA, out bool value, out string msg))
{
if (value)
{
DEBUG("Update() Right A is pressed.");
m_Text.text += "Right A";
}
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6409fd38e11fb2c4a83fc5e2d1dc90e6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,113 @@
// Copyright HTC Corporation All Rights Reserved.
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.XR;
using System.Text;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif
namespace VIVE.OpenXR.Samples.OpenXRInput
{
[RequireComponent(typeof(Text))]
public class TrackerTracking : MonoBehaviour
{
const string LOG_TAG = "VIVE.XR.Sample.OpenXRInput.TrackerTracking ";
StringBuilder m_sb = null;
StringBuilder sb {
get {
if (m_sb == null) { m_sb = new StringBuilder(); }
return m_sb;
}
}
void DEBUG(StringBuilder msg)
{
msg.Insert(0, LOG_TAG);
Debug.Log(msg);
}
[SerializeField]
private int m_Index = 0;
public int Index { get { return m_Index; } set { m_Index = value; } }
[SerializeField]
private InputActionReference m_IsTracked = null;
public InputActionReference IsTracked { get { return m_IsTracked; } set { m_IsTracked = value; } }
[SerializeField]
private InputActionReference m_TrackingState = null;
public InputActionReference TrackingState { get { return m_TrackingState; } set { m_TrackingState = value; } }
[SerializeField]
private InputActionReference m_Position = null;
public InputActionReference Position { get { return m_Position; } set { m_Position = value; } }
[SerializeField]
private InputActionReference m_Rotation = null;
public InputActionReference Rotation { get { return m_Rotation; } set { m_Rotation = value; } }
private Text m_Text = null;
private void Start()
{
m_Text = GetComponent<Text>();
}
void Update()
{
if (m_Text == null) { return; }
m_Text.text = "Tracker" + m_Index;
m_Text.text += " isTracked: ";
{
if (Utils.GetButton(m_IsTracked, out bool value, out string msg))
{
m_Text.text += value;
}
else
{
m_Text.text += msg;
}
}
m_Text.text += "\n";
m_Text.text += "trackingState: ";
{
if (Utils.GetInteger(m_TrackingState, out InputTrackingState value, out string msg))
{
m_Text.text += value;
}
else
{
m_Text.text += msg;
}
}
m_Text.text += "\n";
m_Text.text += "position (";
{
if (Utils.GetVector3(m_Position, out Vector3 value, out string msg))
{
m_Text.text += value.x.ToString() + ", " + value.y.ToString() + ", " + value.z.ToString();
}
else
{
m_Text.text += msg;
}
}
m_Text.text += ")\n";
m_Text.text += "rotation (";
{
if (Utils.GetQuaternion(m_Rotation, out Quaternion value, out string msg))
{
m_Text.text += value.x.ToString() + ", " + value.y.ToString() + ", " + value.z.ToString() + ", " + value.w.ToString();
}
else
{
m_Text.text += msg;
}
}
m_Text.text += ")";
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8712396b9916fe84da21229ef2e2dbb5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,334 @@
// Copyright HTC Corporation All Rights Reserved.
using UnityEngine;
using UnityEngine.XR;
using System;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif
namespace VIVE.OpenXR.Samples.OpenXRInput
{
public static class Utils
{
public enum DeviceTypes : UInt32
{
HMD = 0,
ControllerLeft = 1,
ControllerRight = 2,
Tracker0 = 10,
Tracker1 = 11,
Tracker2 = 12,
Tracker3 = 13,
Tracker4 = 14,
Tracker5 = 15,
Tracker6 = 16,
Tracker7 = 17,
Eye = 3,
}
public enum BinaryButtons : UInt32
{
menuButton,
gripButton,
primaryButton,
primaryTouch,
secondaryButton,
secondaryTouch,
primary2DAxisClick,
primary2DAxisTouch,
triggerButton,
secondary2DAxisClick,
secondary2DAxisTouch,
}
public static InputFeatureUsage<bool> InputFeature(this BinaryButtons button)
{
if (button == BinaryButtons.menuButton) { return UnityEngine.XR.CommonUsages.menuButton; }
if (button == BinaryButtons.gripButton) { return UnityEngine.XR.CommonUsages.gripButton; }
if (button == BinaryButtons.primaryButton) { return UnityEngine.XR.CommonUsages.primaryButton; }
if (button == BinaryButtons.primaryTouch) { return UnityEngine.XR.CommonUsages.primaryTouch; }
if (button == BinaryButtons.secondaryButton) { return UnityEngine.XR.CommonUsages.secondaryButton; }
if (button == BinaryButtons.secondaryTouch) { return UnityEngine.XR.CommonUsages.secondaryTouch; }
if (button == BinaryButtons.primary2DAxisClick) { return UnityEngine.XR.CommonUsages.primary2DAxisClick; }
if (button == BinaryButtons.secondary2DAxisClick) { return UnityEngine.XR.CommonUsages.secondary2DAxisClick; }
if (button == BinaryButtons.triggerButton) { return UnityEngine.XR.CommonUsages.triggerButton; }
if (button == BinaryButtons.primary2DAxisTouch) { return UnityEngine.XR.CommonUsages.primary2DAxisTouch; }
return UnityEngine.XR.CommonUsages.secondary2DAxisTouch;
}
public enum Vector2Buttons : UInt32
{
primary2DAxis,
secondary2DAxis,
}
public static InputFeatureUsage<Vector2> InputFeature(this Vector2Buttons button)
{
if (button == Vector2Buttons.secondary2DAxis) { return UnityEngine.XR.CommonUsages.secondary2DAxis; }
return UnityEngine.XR.CommonUsages.primary2DAxis;
}
public enum FloatButtons : UInt32
{
trigger,
grip
}
public static InputFeatureUsage<float> InputFeature(this FloatButtons button)
{
if (button == FloatButtons.grip) { return UnityEngine.XR.CommonUsages.grip; }
return UnityEngine.XR.CommonUsages.trigger;
}
#if ENABLE_INPUT_SYSTEM
public enum ActionRefError : UInt32
{
NONE = 0,
REFERENCE_NULL = 1,
ACTION_NULL = 2,
DISABLED = 3,
ACTIVECONTROL_NULL = 4,
NO_CONTROLS_COUNT = 5,
}
public static string Name(this ActionRefError error)
{
if (error == ActionRefError.REFERENCE_NULL) { return "Null reference."; }
if (error == ActionRefError.ACTION_NULL) { return "Null reference action."; }
if (error == ActionRefError.DISABLED) { return "Reference action disabled."; }
if (error == ActionRefError.ACTIVECONTROL_NULL) { return "No active control of the reference action."; }
if (error == ActionRefError.NO_CONTROLS_COUNT) { return "No action control count."; }
return "";
}
private static ActionRefError VALIDATE(InputActionReference actionReference)
{
if (actionReference == null) { return ActionRefError.REFERENCE_NULL; }
if (actionReference.action == null) { return ActionRefError.ACTION_NULL; }
if (!actionReference.action.enabled) { return ActionRefError.DISABLED; }
if (actionReference.action.activeControl == null) { return ActionRefError.ACTIVECONTROL_NULL; }
else if (actionReference.action.controls.Count <= 0) { return ActionRefError.NO_CONTROLS_COUNT; }
return ActionRefError.NONE;
}
public static bool GetButton(InputActionReference actionReference, out bool value, out string msg)
{
var result = VALIDATE(actionReference);
value = false;
msg = result.Name();
if (result == ActionRefError.NONE)
{
if (actionReference.action.activeControl.valueType == typeof(float))
value = actionReference.action.ReadValue<float>() > 0;
if (actionReference.action.activeControl.valueType == typeof(bool))
value = actionReference.action.ReadValue<bool>();
return true;
}
return false;
}
public static bool GetAnalog(InputActionReference actionReference, out float value, out string msg)
{
var result = VALIDATE(actionReference);
value = 0;
msg = result.Name();
if (result == ActionRefError.NONE)
{
if (actionReference.action.activeControl.valueType == typeof(float))
value = actionReference.action.ReadValue<float>();
return true;
} else if (result == ActionRefError.ACTIVECONTROL_NULL)
{
value = 0;
return true;
}
return false;
}
public static bool GetInteger(InputActionReference actionReference, out InputTrackingState value, out string msg)
{
var result = VALIDATE(actionReference);
value = 0;
msg = result.Name();
if (result == ActionRefError.NONE)
{
if (actionReference.action.activeControl.valueType == typeof(int))
{
int diff = 0;
int i = actionReference.action.ReadValue<int>();
diff = i & ((int)InputTrackingState.Position);
if (diff != 0) { value |= InputTrackingState.Position; }
diff = i & ((int)InputTrackingState.Rotation);
if (diff != 0) { value |= InputTrackingState.Rotation; }
diff = i & ((int)InputTrackingState.Velocity);
if (diff != 0) { value |= InputTrackingState.Velocity; }
diff = i & ((int)InputTrackingState.AngularVelocity);
if (diff != 0) { value |= InputTrackingState.AngularVelocity; }
diff = i & ((int)InputTrackingState.Acceleration);
if (diff != 0) { value |= InputTrackingState.Acceleration; }
diff = i & ((int)InputTrackingState.AngularAcceleration);
if (diff != 0) { value |= InputTrackingState.AngularAcceleration; }
}
return true;
}
return false;
}
public static bool GetVector3(InputActionReference actionReference, out Vector3 value, out string msg)
{
var result = VALIDATE(actionReference);
value = Vector3.zero;
msg = result.Name();
if (result == ActionRefError.NONE)
{
if (actionReference.action.activeControl.valueType == typeof(Vector3))
value = actionReference.action.ReadValue<Vector3>();
return true;
}
return false;
}
public static bool GetQuaternion(InputActionReference actionReference, out Quaternion value, out string msg)
{
var result = VALIDATE(actionReference);
value = Quaternion.identity;
msg = result.Name();
if (result == ActionRefError.NONE)
{
if (actionReference.action.activeControl.valueType == typeof(Quaternion))
value = actionReference.action.ReadValue<Quaternion>();
Vector3 direction = value * Vector3.forward;
return true;
}
return false;
}
public static bool GetPoseIsTracked(InputActionReference actionReference, out bool value, out string msg)
{
var result = VALIDATE(actionReference);
value = false;
msg = result.Name();
if (result == ActionRefError.NONE)
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.InputSystem.XR.PoseState))
#else
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.XR.OpenXR.Input.Pose))
#endif
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
value = actionReference.action.ReadValue<UnityEngine.InputSystem.XR.PoseState>().isTracked;
#else
value = actionReference.action.ReadValue<UnityEngine.XR.OpenXR.Input.Pose>().isTracked;
#endif
return true;
}
}
return false;
}
public static bool GetPoseTrackingState(InputActionReference actionReference, out InputTrackingState value, out string msg)
{
var result = VALIDATE(actionReference);
value = InputTrackingState.None;
msg = result.Name();
if (result == ActionRefError.NONE)
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.InputSystem.XR.PoseState))
#else
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.XR.OpenXR.Input.Pose))
#endif
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
value = actionReference.action.ReadValue<UnityEngine.InputSystem.XR.PoseState>().trackingState;
#else
value = actionReference.action.ReadValue<UnityEngine.XR.OpenXR.Input.Pose>().trackingState;
#endif
return true;
}
}
return false;
}
public static bool GetPosePosition(InputActionReference actionReference, out Vector3 value, out string msg)
{
var result = VALIDATE(actionReference);
value = Vector3.zero;
msg = result.Name();
if (result == ActionRefError.NONE)
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.InputSystem.XR.PoseState))
#else
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.XR.OpenXR.Input.Pose))
#endif
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
value = actionReference.action.ReadValue<UnityEngine.InputSystem.XR.PoseState>().position;
#else
value = actionReference.action.ReadValue<UnityEngine.XR.OpenXR.Input.Pose>().position;
#endif
return true;
}
}
return false;
}
public static bool GetPoseRotation(InputActionReference actionReference, out Quaternion value, out string msg)
{
var result = VALIDATE(actionReference);
value = Quaternion.identity;
msg = result.Name();
if (result == ActionRefError.NONE)
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.InputSystem.XR.PoseState))
#else
if (actionReference.action.activeControl.valueType == typeof(UnityEngine.XR.OpenXR.Input.Pose))
#endif
{
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
value = actionReference.action.ReadValue<UnityEngine.InputSystem.XR.PoseState>().rotation;
#else
value = actionReference.action.ReadValue<UnityEngine.XR.OpenXR.Input.Pose>().rotation;
#endif
return true;
}
}
return false;
}
#endif
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e1ce74085abd8824e935d6e2df544867
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: