1. 程式人生 > >Unity3d獲取、校準陀螺儀

Unity3d獲取、校準陀螺儀

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
}