陀螺仪和拖动在 3d 房间中一起工作

Posted

技术标签:

【中文标题】陀螺仪和拖动在 3d 房间中一起工作【英文标题】:Gyroscope and Dragging working together in a 3d room 【发布时间】:2021-10-21 14:52:43 【问题描述】:

我正在开发一个统一的应用程序,它基本上是一个 3D 房间,用户可以使用手机的陀螺仪在房间内导航。 我遇到的问题是,我还希望用户能够拖动房间,而在拖动完成后陀螺仪仍然可以工作,但是我的拖动代码效果不佳,而且它也破坏了陀螺仪导航。

我制作了一个视频来更好地解释这个问题:https://youtu.be/7liSyZAdxL4

这是我的陀螺仪代码(它附在相机上):

using UnityEngine;
public class GyroHandler : MonoBehaviour

bool m_gyroEnabled;
UnityEngine.Gyroscope m_gyro;
GameObject m_gyroParent;
Quaternion m_rotation;
float m_rotateAmount = 0;

public static GyroHandler Instance;

void Awake()

    Instance = this;


void Start()

    Screen.sleepTimeout = SleepTimeout.NeverSleep;
    ResetGyro();



void ResetGyro()

    m_gyroParent = new GameObject("Gyro Parent");
    m_gyroParent.transform.position = transform.position;
    transform.SetParent(m_gyroParent.transform);
    m_gyroEnabled = EnableGyro();



bool EnableGyro()

    if (SystemInfo.supportsGyroscope)
    
        m_gyro = Input.gyro;
        m_gyro.enabled = true;
        m_gyroParent.transform.rotation = Quaternion.Euler(90f, -90f, 0f);
        m_rotation = new Quaternion(0, 0, 1, 0);
        return true;
    
    else
        Debug.Log("Device doesn't support gyro.");
    return false;


void Update()

    if (m_gyroEnabled && SystemInfo.supportsGyroscope)
    
        transform.localRotation = m_gyro.attitude * m_rotation;
        transform.Rotate(0, -m_rotateAmount, 0);
    



public void ToggleGyro(bool enable, float rotateAmount)

    m_rotateAmount += rotateAmount;
    m_gyroEnabled = enable;



这是我拖动房间的代码:

using UnityEngine;
using UnityEngine.EventSystems;

public class RoomDragHandler : MonoBehaviour, IDragHandler, IEndDragHandler

    float m_rotateAmount = 0;

    public void OnDrag(PointerEventData eventData)
    
        GyroHandler.Instance.ToggleGyro(false, 0);
        float speedx = eventData.delta.x * 0.05f;
        m_rotateAmount += speedx;
        Camera.main.transform.Rotate(0, -speedx, 0);
    

    public void OnEndDrag(PointerEventData eventData)
    
        GyroHandler.Instance.ToggleGyro(true, m_rotateAmount);
        m_rotateAmount = 0;
    

我的拖拽逻辑是这样的:拖拽开始时,禁用陀螺仪,拖拽完成后,启用陀螺仪返回。当用户拖动时,将拖动量保存在变量 (m_rotateAmount) 中,当拖动完成时,将该值传递给陀螺仪处理程序,以便当陀螺仪再次接管时,它会将相机旋转到该量。如果没有这部分,一旦阻力结束,房间就会迅速恢复,所以我们需要告诉陀螺仪进行额外的旋转。这是执行此操作的代码部分:

void Update()

    if (m_gyroEnabled && SystemInfo.supportsGyroscope)
    
        transform.localRotation = m_gyro.attitude * m_rotation;
        transform.Rotate(0, -m_rotateAmount, 0);
    

第一部分只是使用陀螺仪进行正常旋转,第二行添加了在拖动过程中保存的额外旋转。

我不确定我错过了什么,但我一直在使用这段代码,试图更好地计算数学以了解为什么阻力会破坏陀螺仪,但到目前为止还没有运气。

如果有人能告诉我我做错了什么,我将不胜感激。

非常感谢。

【问题讨论】:

【参考方案1】:

默认transform.Rotate(x, y, z) 围绕对象的局部坐标系旋转,而不是世界坐标系。这意味着当您在应用陀螺仪旋转后应用拖动旋转时,y 轴不再指向正上方,并且应用的旋转不一定在预期的方向上。


解决这个问题:

transform.Rotate(0, -m_rotateAmount, 0, Space.World)

【讨论】:

以上是关于陀螺仪和拖动在 3d 房间中一起工作的主要内容,如果未能解决你的问题,请参考以下文章

使用加速度计、陀螺仪和指南针计算设备在 3D 世界中的运动

Unity 3D中加速度计和陀螺仪的传感器融合

Unity3D中手机陀螺仪的使用

unity3d啥设备才能用陀螺仪

MEMS加速度计 MEMS陀螺仪有啥区别

使用加速度计和陀螺仪获取手机在太空中的大致位置