🌑

脑洞杂货铺

陀螺仪Note

Unity陀螺仪测试记录

简介

  • 本篇介绍了 Unity 中提供的陀螺仪接口,在 Android 平台的陀螺仪实际表现。最后介绍以陀螺仪为输入数据的设备环绕查看目标物体的实现方式。

Unity 中的陀螺仪接口

  • 接口使用方式:
    // 从Input中取陀螺仪的类型数据
    Gyroscope gyro = Input.gyro;
    // 用gyro的各种属性设置或者获取参数来使用陀螺仪
    // 例如:
    gyro.enabled = true; // 开启陀螺仪
    var currGyroAngle = gyro.attitude.eulerAngles; // 获取当前陀螺仪旋转到了的角度
  • 以下是陀螺仪的所有属性参数:
    (类型)属性 说明
    (Quaternion) attitude 返回设备的姿态(即空间方向)。(实测每次开启应用程序后的空间方向零点的坐标不一致。旋转设备方向会改变轴向。)
    (bool) enabled 设置或获取此陀螺仪的启用状态。(使用陀螺仪时要代码设置打开此属性)
    (Vector3) gravity 返回以设备的参考框架表示的重力加速度矢量。(可以用来简单检测设备的当前姿态。旋转设备会改变轴向。)
    (Vector3) rotationRate 返回由设备的陀螺仪测量的旋转速率。(获取设备的旋转偏移量,由于精度问题,真实旋转的角度可能不能严格和获取的数据对应。)
    (Vector3) rotationRateUnbiased 返回由设备的陀螺仪测量的无偏转速。(相对rotationRate数据更稳定建议使用)
    (float) updateInterval 设置或获取陀螺仪间隔(以秒为单位)。 (设置获取设备间隔,控制陀螺仪灵敏度。)
    (Vector3) userAcceleration 返回用户给予设备的加速度。 (可以获取各个轴向的加速度,精度一般。)

设备轴向

  • 设备轴向(Portrait,PortraitUpsideDown,LandscapeLeft,LandscapeRight)以Portrait作为标准方向坐标如下,其他方向是在此基础上做左右旋转得到。不管设备如何朝向,轴向是不会改变的
  • Portrait 设备竖直正方向
    • 设备状态:
      • ┏++┓
      • ┃⇧y┃ 设备向上Y轴
      • ┗==┛
      • ┏++┓
      • ┃⇨x┃ 设备向右X轴
      • ┗==┛
      • ┏++┓
      • ┃◉z┃ 设备向上Z轴
      • ┗==┛
  • PortraitUpsideDown 设备竖直倒方向
    • Portrait 绕z轴旋转180°
  • LandscapeLeft 设备左转方向
    • Portrait 绕z轴逆时针90°
  • LandscapeRight 设备右转方向
    • Portrait 绕z轴顺时针90°

Android 平台

  • gyro.attitude.eulerAngles 陀螺仪状态角,的值始终与内容方向一致。
    • 具体解释
      • 假设设备屏幕朝上放在桌子上,设备内容与现实世界北方方向相同。
      • N
      • ┏++┓
      • ┃⇧⇧┃
      • ┗==┛ Portrait, gyro.attitude.eulerAngles = 0°
      • S
      • 当设备方向从Portrait变成PortraitUpsideDown时,设备内容会变化朝向南方,陀螺仪状态角也会与原来相差180°。
      • N
      • ┏==┓
      • ┃⇩⇩┃
      • ┗++┛ PortraitUpsideDown, gyro.attitude.eulerAngles = 180°
      • S
      • 这时要将内容方向与现实世界对齐,要旋转设备180°,让内容与现实世界对齐。陀螺仪角度也会随之归位到开始时的角度。
      • N
      • ┏++┓
      • ┃⇧⇧┃
      • ┗==┛ PortraitUpsideDown, gyro.attitude.eulerAngles =
      • S
      • 变化的是设备的方向被旋转了、设备的朝向模式装变成了PortraitUpsideDown。
      • 总结
        • 陀螺仪状态角内容朝向 相对应。不管设备轴向怎么变化,他们的对应关系不会变。
        • 设备轴向变化时,可以让旋转设备与轴向变化前相同即可实现,将内容朝向恢复到轴变化前的朝向姿态。

借助陀螺仪实现设备环绕查看物体功能

  • 利用陀螺仪状态角,可完成精准的360°环绕查看(旋转移动相机)
    using UnityEngine;
    // 脚本挂载到相机上
    public class SurroundView : MonoBehaviour
    {
       public GameObject targetObj;
       private Gyroscope gyro;
       private float distance;
       void Start()
       {
          gyro = Input.gyro;
          gyro.enabled = true;
          distance = Vector3.Distance(transform.position, targetObj.transform.position);
       }
       void Update()
       {
          transform.LookAt(targetObj.transform.position);
          var targetPos = new Vector3(
            (float)(System.Math.Sin(System.Math.PI * gyro.attitude.eulerAngles.x / 180)) * distance,
            (float)(System.Math.Cos(System.Math.PI * gyro.attitude.eulerAngles.y / 180)) * distance,
            (float)(System.Math.Sin(System.Math.PI * gyro.attitude.eulerAngles.y / 180)) * distance);
          transform.position = Vector3.Lerp(transform.position, targetPos, Time.deltaTime * 2);
       }
    }
    • 脚本要点解析:
      • targetPos值的确定:(设:相机到目标物体距离为a,)
        • GyroX角控制水平环绕,GyroX角只控制XPos,所以单独用GyroX计算。
          • x = sin(GyroX)a
        • GyroY角控制垂直环绕,GyroY角控制YPos、ZPos,所用这两个的值在一个平面一个角算。
          • y = cos(GyroY)a
          • z = sin(GyroY)a
  • 利用陀螺仪旋转速度向量,可完成精度较低的环绕查看(旋转模型)
    using UnityEngine;
    // 挂载到被控制的物体上
    public class GyroObj : MonoBehaviour
    {
        public float speed = 1; // 调节旋转速度
        private Gyroscope gyro;
        private void Start()
        {
            gyro = Input.gyro;
            gyro.enabled = true;
        }
        private void Update()
        {
            gameObject.transform.Rotate(gyro.rotationRate * speed, Space.World);
        }
    }

— 2021年3月15日