Unity3d獲取、校準陀螺儀
阿新 • • 發佈:2019-02-06
using System.Collections; using System.Collections.Generic; using UnityEngine; public class GyroscopeCtrl : MonoBehaviour { //陀螺儀是否啟動 bool gyinfo; //陀螺儀狀態 private static GyroscpeState state; #region [Private fields] private bool gyroEnabled = true; private const float lowPassFilterFactor = 0.2f; private readonly Quaternion baseIdentity = Quaternion.Euler(90, 0, 0); private readonly Quaternion landscapeRight = Quaternion.Euler(0, 0, 90); private readonly Quaternion landscapeLeft = Quaternion.Euler(0, 0, -90); private readonly Quaternion upsideDown = Quaternion.Euler(0, 0, 180); private Quaternion cameraBase = Quaternion.identity; private Quaternion calibration = Quaternion.identity; private Quaternion baseOrientation = Quaternion.Euler(90, 0, 0); private Quaternion baseOrientationRotationFix = Quaternion.identity; private Quaternion referanceRotation = Quaternion.identity; private bool debug = true; #endregion #region [Unity events] void Start() { AttachGyro(); StartCoroutine(DelayCtrl()); } void Update() { #if UNITY_EDITOR //pc端實現旋轉測試的方法 transform.Rotate(new Vector3(/*-Input.GetAxis("Mouse Y")*/0, Input.GetAxis("Mouse X"), 0)); #elif UNITY_ANDROID||UNITY_IPHONE||UNITY_IOS if (!gyroEnabled) return; transform.rotation = Quaternion.Slerp(transform.rotation, cameraBase * (ConvertRotation(referanceRotation * Input.gyro.attitude) * GetRotFix()), lowPassFilterFactor); //向左走的方法 if (transform.rotation.z > 0.2f) { //transform.position += new Vector3(-1,0,0); state = GyroscpeState.left; // text.text = "向左偏移"; } ///向右偏移的方法 if (transform.rotation.z < -0.2f) { // transform.position += new Vector3(1,0,0); state = GyroscpeState.right; //text.text = "向右偏移"; } if (transform.rotation.z < 0.2f && transform.rotation.z > -0.2f) { state = GyroscpeState.mid; } // text.text = state.ToString(); #endif } void OnGUI() { #if UNITY_EDITOR // return; //GUILayout.Label("方向: " + Screen.orientation); //GUILayout.Label("校準: " + calibration); //GUILayout.Label("攝像頭底座: " + cameraBase); //GUILayout.Label("陀螺儀狀態: " + Input.gyro.attitude); //GUILayout.Label("變換的旋轉: " + transform.rotation); //if (GUILayout.Button("ON / OFF陀螺儀: " + Input.gyro.enabled, GUILayout.Height(30))) //{ // GyroscopeEnabled(); //} //if (GUILayout.Button("ON / OFF陀螺儀控制器: " + gyroEnabled, GUILayout.Height(30))) //{ // if (gyroEnabled) // { // DetachGyro(); // } // else // { // AttachGyro(); // } //} //if (GUILayout.Button("更新陀螺儀校準(水平)", GUILayout.Height(30))) //{ // UpdateCalibration(true); //} //if (GUILayout.Button("更新相機基地旋轉(水平)", GUILayout.Height(30))) //{ // UpdateCameraBaseRotation(true); //} //if (GUILayout.Button("復位的基本取向", GUILayout.Height(30))) //{ // ResetBaseOrientation(); //} //if (GUILayout.Button("復位旋轉攝像頭", GUILayout.Height(30))) //{ // transform.rotation = Quaternion.identity; //} #elif UNITY_ANDROID||UNITY_IPHONE||UNITY_IOS #endif } #endregion #region [Public methods] private void GyroscopeEnabled() { Input.gyro.enabled = !Input.gyro.enabled; } IEnumerator DelayCtrl() { yield return new WaitForSeconds(0.5f); Input.gyro.enabled = true; Input.gyro.enabled = true; } /// <summary> /// 將陀螺控制器連線到變換. /// </summary> private void AttachGyro() { state = new GyroscpeState(); state = GyroscpeState.mid; gyroEnabled = true; ResetBaseOrientation(); UpdateCalibration(true); UpdateCameraBaseRotation(true); RecalculateReferenceRotation(); #if UNITY_EDITOR #elif UNITY_ANDROID||UNITY_IPHONE||UNITY_IOS gyinfo = SystemInfo.supportsGyroscope; //陀螺儀提示 if (!gyinfo) { WpsteMainCtrl.Instance.ShowGyroscopeTip(); } #endif } /// <summary> /// 將陀螺控制器從變換 /// </summary> private void DetachGyro() { gyroEnabled = false; } #endregion #region [Private methods] /// <summary> /// 更新陀螺校準。 /// </summary> private void UpdateCalibration(bool onlyHorizontal) { if (onlyHorizontal) { var fw = (Input.gyro.attitude) * (-Vector3.forward); fw.z = 0; if (fw == Vector3.zero) { calibration = Quaternion.identity; } else { calibration = (Quaternion.FromToRotation(baseOrientationRotationFix * Vector3.up, fw)); } } else { calibration = Input.gyro.attitude; } } /// <summary> /// 更新相機底座旋轉。 /// </summary> /// <param name='onlyHorizontal'> /// 只有Y旋轉。 /// </param> private void UpdateCameraBaseRotation(bool onlyHorizontal) { if (onlyHorizontal) { var fw = transform.forward; fw.y = 0; if (fw == Vector3.zero) { cameraBase = Quaternion.identity; } else { cameraBase = Quaternion.FromToRotation(Vector3.forward, fw); } } else { cameraBase = transform.rotation; } } /// <summary> /// 將旋轉從右交給左手。 /// </summary> /// <returns> ///返回角度 /// </returns> /// <param name='q'> /// 旋轉轉換。 /// </param> private static Quaternion ConvertRotation(Quaternion q) { return new Quaternion(q.x, q.y, -q.z, -q.w); } /// <summary> /// 獲得不同方向的修復。 /// </summary> /// <returns> /// The rot fix. /// </returns> private Quaternion GetRotFix() { #if UNITY_3_5 if (Screen.orientation == ScreenOrientation.Portrait) return Quaternion.identity; if (Screen.orientation == ScreenOrientation.LandscapeLeft || Screen.orientation == ScreenOrientation.Landscape) return landscapeLeft; if (Screen.orientation == ScreenOrientation.LandscapeRight) return landscapeRight; if (Screen.orientation == ScreenOrientation.PortraitUpsideDown) return upsideDown; return Quaternion.identity; #else return Quaternion.identity; #endif } /// <summary> /// 重新計算的參考系統。 /// </summary> private void ResetBaseOrientation() { baseOrientationRotationFix = GetRotFix(); baseOrientation = baseOrientationRotationFix * baseIdentity; } /// <summary> /// 重新計算基準旋轉。 /// </summary> private void RecalculateReferenceRotation() { referanceRotation = Quaternion.Inverse(baseOrientation) * Quaternion.Inverse(calibration); } #endregion }