using UnityEngine; using Valve.VR; using TMPro; using System.Runtime.InteropServices; using System.Text; public class RawGyroscopeReader : MonoBehaviour { [Header("References")] public TextMeshProUGUI gyroText; [Header("Settings")] [Tooltip("Whether to try using the native plugin")] public bool useNativePlugin = true; [Tooltip("Whether to try using the SteamVR plugin")] public bool useSteamVRPlugin = true; // Components private SteamVRGyroscope steamVRGyro; // Native plugin status private bool nativePluginInitialized = false; void Start() { Debug.Log("RawGyroscopeReader: Start called"); if (gyroText == null) { Debug.LogError("TextMeshProUGUI reference not set"); return; } // Initialize OpenVR if not already initialized if (OpenVR.System == null) { OpenVRUtil.System.InitOpenVR(); } // Try to initialize the native plugin if (useNativePlugin) { try { nativePluginInitialized = OpenVRNativeAccess.InitializePlugin(); if (nativePluginInitialized) { Debug.Log("Native plugin initialized successfully"); Debug.Log($"Driver name: {OpenVRNativeAccess.GetDriverNameString()}"); } else { Debug.LogWarning("Failed to initialize native plugin"); } } catch (System.Exception e) { Debug.LogError($"Error initializing native plugin: {e.Message}"); useNativePlugin = false; } } // Try to use the SteamVR plugin if (useSteamVRPlugin) { // Add the SteamVRGyroscope component if it doesn't exist steamVRGyro = GetComponent(); if (steamVRGyro == null) { steamVRGyro = gameObject.AddComponent(); } } // Log information about available methods StringBuilder methods = new StringBuilder("Available gyroscope access methods:\n"); if (useNativePlugin && nativePluginInitialized) { methods.AppendLine("- Native plugin (direct driver access)"); } if (useSteamVRPlugin && steamVRGyro != null) { methods.AppendLine("- SteamVR Unity plugin"); } methods.AppendLine("- Standard OpenVR tracking pose"); Debug.Log(methods.ToString()); } void Update() { if (gyroText == null) return; // Method 1: Try to get data from the native plugin if (useNativePlugin && nativePluginInitialized) { float x, y, z; bool success = OpenVRNativeAccess.GetRawGyroscopeData(out x, out y, out z); if (success) { gyroText.text = string.Format("Native Gyro:\nX: {0:F2}\nY: {1:F2}\nZ: {2:F2}", x, y, z); // Add tracking status bool trackingValid = OpenVRNativeAccess.IsTrackingValid(); if (!trackingValid) { gyroText.text += "\n(Tracking lost)"; } return; } } // Method 2: Fall back to standard tracking pose uint headsetIndex = OpenVR.k_unTrackedDeviceIndex_Hmd; // Make sure the headset is connected if (OpenVR.System == null || !OpenVR.System.IsTrackedDeviceConnected(headsetIndex)) { gyroText.text = "Headset not connected"; return; } // Get tracking data 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)"; } } void OnDestroy() { // Shutdown the native plugin if it was initialized if (nativePluginInitialized) { try { OpenVRNativeAccess.ShutdownPlugin(); Debug.Log("Native plugin shut down"); } catch (System.Exception e) { Debug.LogError($"Error shutting down native plugin: {e.Message}"); } } } }