GyroController.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. using UnityEngine;
  2. /// <summary>
  3. /// Gyroscope controller that works with any device orientation.
  4. /// </summary>
  5. public class GyroController : MonoBehaviour
  6. {
  7. #region [Private fields]
  8. private bool gyroEnabled = true; //陀螺仪是否可用
  9. private const float lowPassFilterFactor = 0.2f;
  10. private readonly Quaternion baseIdentity = Quaternion.Euler(90, 0, 0);
  11. private readonly Quaternion landscapeRight = Quaternion.Euler(0, 0, 90);
  12. private readonly Quaternion landscapeLeft = Quaternion.Euler(0, 0, -90);
  13. private readonly Quaternion upsideDown = Quaternion.Euler(0, 0, 180);
  14. private Quaternion cameraBase = Quaternion.identity;
  15. private Quaternion calibration = Quaternion.identity;
  16. private Quaternion baseOrientation = Quaternion.Euler(90, 0, 0);
  17. private Quaternion baseOrientationRotationFix = Quaternion.identity;
  18. private Quaternion referanceRotation = Quaternion.identity;
  19. private bool debug = true;
  20. #endregion
  21. #region [Unity events]
  22. protected void Start()
  23. {
  24. AttachGyro(); //初始化并且设置陀螺仪参数
  25. }
  26. protected void Update()
  27. {
  28. if (!gyroEnabled)
  29. return; //不可用陀螺仪则返回
  30. transform.rotation = Quaternion.Slerp(transform.rotation,
  31. cameraBase * (ConvertRotation(referanceRotation * Input.gyro.attitude) * GetRotFix()), lowPassFilterFactor*50);
  32. //相机的角度等于从当前相机旋转角度慢慢转向矫正后的角度,最后的参数是矫正的速度
  33. }
  34. /* protected void OnGUI()
  35. {
  36. if (!debug)
  37. return;
  38. GUILayout.Label("Orientation: " + Screen.orientation);
  39. GUILayout.Label("Calibration: " + calibration);
  40. GUILayout.Label("Camera base: " + cameraBase);
  41. GUILayout.Label("input.gyro.attitude: " + Input.gyro.attitude);
  42. GUILayout.Label("transform.rotation: " + transform.rotation);
  43. if (GUILayout.Button("On/off gyro: " + Input.gyro.enabled, GUILayout.Height(100)))
  44. {
  45. Input.gyro.enabled = !Input.gyro.enabled; //设置陀螺仪是否可用
  46. }
  47. if (GUILayout.Button("On/off gyro controller: " + gyroEnabled, GUILayout.Height(100)))
  48. {
  49. if (gyroEnabled)
  50. {
  51. DetachGyro(); //删除陀螺仪感应
  52. }
  53. else
  54. {
  55. AttachGyro(); //设置陀螺仪感应
  56. }
  57. }
  58. if (GUILayout.Button("Update gyro calibration (Horizontal only)", GUILayout.Height(80)))
  59. {
  60. UpdateCalibration(true);
  61. }
  62. if (GUILayout.Button("Update camera base rotation (Horizontal only)", GUILayout.Height(80)))
  63. {
  64. UpdateCameraBaseRotation(true);
  65. }
  66. if (GUILayout.Button("Reset base orientation", GUILayout.Height(80)))
  67. {
  68. ResetBaseOrientation();
  69. }
  70. if (GUILayout.Button("Reset camera rotation", GUILayout.Height(80)))
  71. {
  72. transform.rotation = Quaternion.identity;
  73. }
  74. }*/
  75. #endregion
  76. #region [Public methods]
  77. /// <summary>
  78. /// Attaches gyro controller to the transform.
  79. /// </summary>
  80. private void AttachGyro()
  81. {
  82. gyroEnabled = true; //设置陀螺仪可用
  83. ResetBaseOrientation(); //重置基本方向
  84. UpdateCalibration(true); //更新校准
  85. UpdateCameraBaseRotation(true); //更新相机旋转角度
  86. RecalculateReferenceRotation(); //重新计算当前角度
  87. }
  88. /// <summary>
  89. /// Detaches gyro controller from the transform
  90. /// </summary>
  91. private void DetachGyro()
  92. {
  93. gyroEnabled = false;
  94. }
  95. #endregion
  96. #region [Private methods]
  97. /// <summary>
  98. /// Update the gyro calibration.
  99. /// </summary>
  100. private void UpdateCalibration(bool onlyHorizontal) //设置校准值Calibration
  101. {
  102. if (onlyHorizontal) //仅按照陀螺仪所在的水平面校准
  103. {
  104. var fw = (Input.gyro.attitude) * (-Vector3.forward);
  105. fw.z = 0;
  106. if (fw == Vector3.zero)
  107. {
  108. calibration = Quaternion.identity;
  109. }
  110. else
  111. {
  112. calibration = (Quaternion.FromToRotation(baseOrientationRotationFix * Vector3.up, fw));
  113. }
  114. }
  115. else //根据陀螺仪的水平和垂直方向校准
  116. {
  117. calibration = Input.gyro.attitude;
  118. }
  119. }
  120. /// <summary>
  121. /// Update the camera base rotation.
  122. /// </summary>
  123. /// <param name='onlyHorizontal'>
  124. /// Only y rotation.
  125. /// </param>
  126. private void UpdateCameraBaseRotation(bool onlyHorizontal) //更新相机所在位置的旋转方向
  127. {
  128. if (onlyHorizontal) //仅水平更新
  129. {
  130. var fw = transform.forward;
  131. fw.y = 0;
  132. if (fw == Vector3.zero)
  133. {
  134. cameraBase = Quaternion.identity;
  135. }
  136. else
  137. {
  138. cameraBase = Quaternion.FromToRotation(Vector3.forward, fw);
  139. }
  140. }
  141. else //从水平和垂直方向更新
  142. {
  143. cameraBase = transform.rotation;
  144. }
  145. }
  146. /// <summary>
  147. /// Converts the rotation from right handed to left handed.
  148. /// </summary>
  149. /// <returns>
  150. /// The result rotation.
  151. /// </returns>
  152. /// <param name='q'>
  153. /// The rotation to convert.
  154. /// </param>
  155. private static Quaternion ConvertRotation(Quaternion q) //返回一个方向值
  156. {
  157. return new Quaternion(q.x, q.y, -q.z, -q.w);
  158. }
  159. /// <summary>
  160. /// Gets the rot fix for different orientations.
  161. /// </summary>
  162. /// <returns>
  163. /// The rot fix.
  164. /// </returns>
  165. private Quaternion GetRotFix() //获取对应屏幕不同型号的修正值
  166. {
  167. #if UNITY_3_5
  168. if (Screen.orientation == ScreenOrientation.Portrait) //如果软件设置手机竖屏
  169. return Quaternion.identity;
  170. if (Screen.orientation == ScreenOrientation.LandscapeLeft || Screen.orientation == ScreenOrientation.Landscape) //左横屏
  171. return landscapeLeft;
  172. if (Screen.orientation == ScreenOrientation.LandscapeRight) //右横屏
  173. return landscapeRight;
  174. if (Screen.orientation == ScreenOrientation.PortraitUpsideDown) //下竖屏
  175. return upsideDown;
  176. return Quaternion.identity;
  177. #else
  178. return Quaternion.identity;
  179. #endif
  180. }
  181. /// <summary>
  182. /// Recalculates reference system.
  183. /// </summary>
  184. private void ResetBaseOrientation()
  185. {
  186. baseOrientationRotationFix = GetRotFix();
  187. baseOrientation = baseOrientationRotationFix * baseIdentity;
  188. }
  189. /// <summary>
  190. /// Recalculates reference rotation.
  191. /// </summary>
  192. private void RecalculateReferenceRotation()
  193. {
  194. referanceRotation = Quaternion.Inverse(baseOrientation) * Quaternion.Inverse(calibration);
  195. }
  196. #endregion
  197. }