123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- using UnityEngine;
- /// <summary>
- /// Gyroscope controller that works with any device orientation.
- /// </summary>
- public class GyroController : MonoBehaviour
- {
- #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]
- protected void Start()
- {
- AttachGyro(); //初始化并且设置陀螺仪参数
- }
- protected void Update()
- {
- if (!gyroEnabled)
- return; //不可用陀螺仪则返回
- transform.rotation = Quaternion.Slerp(transform.rotation,
- cameraBase * (ConvertRotation(referanceRotation * Input.gyro.attitude) * GetRotFix()), lowPassFilterFactor*50);
- //相机的角度等于从当前相机旋转角度慢慢转向矫正后的角度,最后的参数是矫正的速度
- }
- /* protected void OnGUI()
- {
- if (!debug)
- return;
- GUILayout.Label("Orientation: " + Screen.orientation);
- GUILayout.Label("Calibration: " + calibration);
- GUILayout.Label("Camera base: " + cameraBase);
- GUILayout.Label("input.gyro.attitude: " + Input.gyro.attitude);
- GUILayout.Label("transform.rotation: " + transform.rotation);
- if (GUILayout.Button("On/off gyro: " + Input.gyro.enabled, GUILayout.Height(100)))
- {
- Input.gyro.enabled = !Input.gyro.enabled; //设置陀螺仪是否可用
- }
- if (GUILayout.Button("On/off gyro controller: " + gyroEnabled, GUILayout.Height(100)))
- {
- if (gyroEnabled)
- {
- DetachGyro(); //删除陀螺仪感应
- }
- else
- {
- AttachGyro(); //设置陀螺仪感应
- }
- }
- if (GUILayout.Button("Update gyro calibration (Horizontal only)", GUILayout.Height(80)))
- {
- UpdateCalibration(true);
- }
- if (GUILayout.Button("Update camera base rotation (Horizontal only)", GUILayout.Height(80)))
- {
- UpdateCameraBaseRotation(true);
- }
- if (GUILayout.Button("Reset base orientation", GUILayout.Height(80)))
- {
- ResetBaseOrientation();
- }
- if (GUILayout.Button("Reset camera rotation", GUILayout.Height(80)))
- {
- transform.rotation = Quaternion.identity;
- }
- }*/
- #endregion
- #region [Public methods]
- /// <summary>
- /// Attaches gyro controller to the transform.
- /// </summary>
- private void AttachGyro()
- {
- gyroEnabled = true; //设置陀螺仪可用
- ResetBaseOrientation(); //重置基本方向
- UpdateCalibration(true); //更新校准
- UpdateCameraBaseRotation(true); //更新相机旋转角度
- RecalculateReferenceRotation(); //重新计算当前角度
- }
- /// <summary>
- /// Detaches gyro controller from the transform
- /// </summary>
- private void DetachGyro()
- {
- gyroEnabled = false;
- }
- #endregion
- #region [Private methods]
- /// <summary>
- /// Update the gyro calibration.
- /// </summary>
- private void UpdateCalibration(bool onlyHorizontal) //设置校准值Calibration
- {
- 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>
- /// Update the camera base rotation.
- /// </summary>
- /// <param name='onlyHorizontal'>
- /// Only y rotation.
- /// </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>
- /// Converts the rotation from right handed to left handed.
- /// </summary>
- /// <returns>
- /// The result rotation.
- /// </returns>
- /// <param name='q'>
- /// The rotation to convert.
- /// </param>
- private static Quaternion ConvertRotation(Quaternion q) //返回一个方向值
- {
- return new Quaternion(q.x, q.y, -q.z, -q.w);
- }
- /// <summary>
- /// Gets the rot fix for different orientations.
- /// </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>
- /// Recalculates reference system.
- /// </summary>
- private void ResetBaseOrientation()
- {
- baseOrientationRotationFix = GetRotFix();
- baseOrientation = baseOrientationRotationFix * baseIdentity;
- }
- /// <summary>
- /// Recalculates reference rotation.
- /// </summary>
- private void RecalculateReferenceRotation()
- {
- referanceRotation = Quaternion.Inverse(baseOrientation) * Quaternion.Inverse(calibration);
- }
- #endregion
- }
|