using UnityEngine; using Valve.VR; using TMPro; using System.Runtime.InteropServices; using System.Text; using System.Collections.Generic; public class SteamVRGyroscope : MonoBehaviour { private TextMeshProUGUI gyroText; private uint headsetIndex = OpenVR.k_unTrackedDeviceIndex_Hmd; // SteamVR-specific variables private SteamVR_TrackedObject trackedObject; private SteamVR_Events.Action deviceConnectedAction; // For direct driver access private const string OPENVR_DLL = "openvr_api"; [DllImport(OPENVR_DLL)] private static extern IntPtr VR_GetGenericInterface([MarshalAs(UnmanagedType.LPStr)] string pchInterfaceVersion, ref EVRInitError peError); void Start() { Debug.Log("SteamVRGyroscope: Start called"); gyroText = GetComponent(); if (gyroText == null) { Debug.LogError("TextMeshProUGUI component not found on this GameObject"); } // Initialize OpenVR if not already initialized if (OpenVR.System == null) { OpenVRUtil.System.InitOpenVR(); } // Try to find a SteamVR_TrackedObject in the scene trackedObject = FindObjectOfType(); if (trackedObject == null) { Debug.LogWarning("No SteamVR_TrackedObject found in the scene. Creating one."); GameObject trackedObj = new GameObject("HeadsetTrackedObject"); trackedObject = trackedObj.AddComponent(); trackedObject.index = SteamVR_TrackedObject.EIndex.Hmd; } // Subscribe to device connected events deviceConnectedAction = SteamVR_Events.DeviceConnectedAction(OnDeviceConnected); // Try to access driver-level interfaces TryAccessDriverInterfaces(); } void OnDeviceConnected(int index, bool connected) { if (index == (int)headsetIndex && connected) { Debug.Log($"Headset connected: {index}"); // Try to get device class ETrackedDeviceClass deviceClass = OpenVR.System.GetTrackedDeviceClass((uint)index); Debug.Log($"Device class: {deviceClass}"); } } void Update() { if (OpenVR.System == null || gyroText == null) return; // Make sure the headset is connected if (!OpenVR.System.IsTrackedDeviceConnected(headsetIndex)) { gyroText.text = "Headset not connected"; return; } // Try different methods to get gyroscope data // Method 1: Try to use SteamVR_Controller.Device Vector3 gyroData = TryGetSteamVRControllerGyro(); if (gyroData != Vector3.zero) { gyroText.text = string.Format("SteamVR Gyro:\nX: {0:F2}\nY: {1:F2}\nZ: {2:F2}", gyroData.x, gyroData.y, gyroData.z); return; } // Method 2: Try to use SteamVR_TrackedObject if (trackedObject != null && SteamVR.instance != null) { // Get the pose from SteamVR var pose = new SteamVR_Utils.RigidTransform(trackedObject.transform); var deviceIndex = (int)trackedObject.index; if (deviceIndex >= 0) { // Try to get angular velocity from SteamVR var system = OpenVR.System; if (system != null) { var controllerState = new VRControllerState_t(); var size = (uint)Marshal.SizeOf(typeof(VRControllerState_t)); system.GetControllerState((uint)deviceIndex, ref controllerState, size); // Log controller state data Debug.Log($"Controller state: {controllerState.ulButtonPressed}"); } } } // Method 3: Fall back to standard tracking pose TrackedDevicePose_t[] poses = new TrackedDevicePose_t[OpenVR.k_unMaxTrackedDeviceCount]; OpenVR.System.GetDeviceToAbsoluteTrackingPose(ETrackingUniverseOrigin.TrackingUniverseStanding, 0, poses); if (!poses[headsetIndex].bDeviceIsConnected) { gyroText.text = "No gyro data available"; return; } // Extract angular velocity from the pose Vector3 angularVelocity = new Vector3( poses[headsetIndex].vAngularVelocity.v0, poses[headsetIndex].vAngularVelocity.v1, poses[headsetIndex].vAngularVelocity.v2 ); // Format and display the gyroscope data gyroText.text = string.Format("Std Gyro:\nX: {0:F2}\nY: {1:F2}\nZ: {2:F2}", angularVelocity.x, angularVelocity.y, angularVelocity.z ); // Add tracking status info if (!poses[headsetIndex].bPoseIsValid) { gyroText.text += "\n(Tracking lost)"; } } private Vector3 TryGetSteamVRControllerGyro() { // Try to use SteamVR_Controller.Device to get gyro data // This is a placeholder for SteamVR_Controller API access try { // This approach uses reflection to access SteamVR_Controller.Device // since the API might change between SteamVR versions var controllerClass = System.Type.GetType("Valve.VR.SteamVR_Controller"); if (controllerClass != null) { var deviceMethod = controllerClass.GetMethod("Device", new System.Type[] { typeof(int) }); if (deviceMethod != null) { var device = deviceMethod.Invoke(null, new object[] { (int)headsetIndex }); if (device != null) { var angularVelocityProperty = device.GetType().GetProperty("angularVelocity"); if (angularVelocityProperty != null) { var angularVelocity = angularVelocityProperty.GetValue(device); if (angularVelocity != null && angularVelocity is Vector3) { return (Vector3)angularVelocity; } } } } } } catch (System.Exception e) { Debug.LogWarning($"Error accessing SteamVR_Controller: {e.Message}"); } return Vector3.zero; } private void TryAccessDriverInterfaces() { // Try to access driver-level interfaces Debug.Log("Attempting to access driver-level interfaces..."); try { // Try to get IVRDriverInput interface EVRInitError error = EVRInitError.None; IntPtr driverInputPtr = VR_GetGenericInterface("IVRDriverInput_005", ref error); if (error != EVRInitError.None) { Debug.LogWarning($"Failed to get IVRDriverInput interface: {error}"); } else if (driverInputPtr != IntPtr.Zero) { Debug.Log("Successfully obtained IVRDriverInput interface"); // We would need to define the interface structure and methods to use this } // Try other interfaces string[] interfaceNames = new string[] { "IVRSettings_002", "IVRDriverManager_001", "IVRResources_001", "IVRDriverLog_001" }; foreach (var interfaceName in interfaceNames) { error = EVRInitError.None; IntPtr interfacePtr = VR_GetGenericInterface(interfaceName, ref error); if (error == EVRInitError.None && interfacePtr != IntPtr.Zero) { Debug.Log($"Successfully obtained {interfaceName} interface"); } else { Debug.LogWarning($"Failed to get {interfaceName} interface: {error}"); } } } catch (System.Exception e) { Debug.LogError($"Error accessing driver interfaces: {e.Message}"); } } }