需要罗盘帮助的陀螺仪

时间:2017-10-26 00:09:52

标签: c# unity3d quaternions gyroscope

我需要将游戏对象指向北方并且我想将其与gyro.attitude输入结合起来。我曾尝试过,但没有成功,只需一步即可完成。也就是说,我无法制作任何我在网上找到的陀螺脚本,它总是指向北方的额外要求。相信我,我已经尝试了我能找到的关于这个主题的每个脚本。我推断,认为可以做到这一点是不可能的,也许是愚蠢的;至少不是这种方式(即一体化)。我想你可以说我猜测你不能同时做两件事。然后我想可能通过分手来达到同样的效果。也就是说,游戏对象总是通过Y轴指向北方。太棒了,完成了这样的事情:

_parentDummyRotationObject.transform.rotation = Quaternion.Slerp(_parentDummyRotationObject.transform.rotation, Quaternion.Euler(0, 360 - Input.compass.trueHeading, 0), Time.deltaTime * 5f);

当游戏对象指向Y的北方时,我想在X和Z轴上使用陀螺仪输入添加第二个游戏对象,在这种情况下是一个摄像机。我必须消除相机上Y轴的原因是因为我得到了双重旋转。当两个物体同时旋转时(即相机和游戏物体),180度旋转在场景中产生360度。请记住,我需要游戏对象始终指向北(IRL)基于设备指南针。如果我的设备指向东方,那么我的游戏对象将在统一场景中旋转90度,因为它指向(旋转)朝北。

我已经阅读了很多关于陀螺仪相机控制器的内容,我看到提到的一件事是你不应该试图在1或2轴上做这个(限制它),当使用四元数时,你不可能知道你在做什么,我显然不知道。

我已经尝试了这个问题的所有3个解决方案:Unity - Gyroscope - Rotation Around One Axis Only并且每个都无法在1轴上旋转我的相机以满足我的旋转需求。想象我试着让1轴工作,然后用第2轴弄脏水。顺便说一句,我的要求很简单,相机应该只根据我的设备的X轴在1轴(任何方向)上旋转。如果我能解决X问题,那么我认为让Z陀螺仪输入控制相机也很棒。到目前为止,我无法仅在1轴(X)上控制相机。无论如何,这是我的发现......

第一个使用Input.gyro.rotationRateUnbiased的解决方案完全不准确。也就是说,如果我将设备旋转几次然后将我的手机/设备放在桌面上,则每次相机将处于不同的旋转/位置。没有一致性。这是我的第一次尝试/解决方案的代码:

<code>
private void Update()
{
  Vector3 previousEulerAngles = transform.eulerAngles;
  Vector3 gyroInput = Input.gyro.rotationRateUnbiased;
  Vector3 targetEulerAngles = previousEulerAngles + gyroInput * Time.deltaTime * Mathf.Rad2Deg;
  targetEulerAngles.y = 0.0f; 
  targetEulerAngles.z = 0.0f;
  transform.eulerAngles = targetEulerAngles;
}
</code>

第二种解决方案非常一致,因为我可以旋转我的设备,然后将其放在桌面上,统一摄像头总是在相同的位置/旋转/状态下结束。我遇到的问题是相机会在一个轴上旋转(在这种情况下为X),但是当我在y轴或x轴上旋转设备时它会这样做。我的手机的任何一种旋转/移动都会导致统一摄像头在X上移动。我不明白为什么手机的y旋转导致摄像头在X上旋转。这是我的解决方案#2的代码:

    private void Start()
{
  Input.gyro.enabled = true;
  startEulerAngles = transform.eulerAngles;
  startGyroAttitudeToEuler = Input.gyro.attitude.eulerAngles;
}
private void Update()
{
  Vector3 deltaEulerAngles = Input.gyro.attitude.eulerAngles - startGyroAttitudeToEuler;
  deltaEulerAngles.y = 0.0f;
  deltaEulerAngles.z = 0.0f;
  transform.eulerAngles = startEulerAngles - deltaEulerAngles;
}

第三种解决方案:我不确定如何完成最后一个解决方案,因此它从未真正起作用。在2轴归零的情况下,相机只是从左向右翻转,从上到下,从上到下翻转;取决于哪个轴被注释掉了。如果没有任何轴被注释掉(就像原始解决方案一样),相机将在所有轴上旋转。这是我尝试#3的代码:

    private void Start()
{
  _upVec = Vector3.zero;
  Input.gyro.enabled = true;
  startEulerAngles = transform.eulerAngles;
}
private void Update()
{
  Vector3 gyroEuler = Input.gyro.attitude.eulerAngles;
  phoneDummy.transform.eulerAngles = new Vector3(-1.0f * gyroEuler.x, -1.0f * gyroEuler.y, gyroEuler.z);
  _upVec = phoneDummy.transform.InverseTransformDirection(-1f * Vector3.forward);
  _upVec.z = 0;
//    _upVec.x = 0;
  _upVec.y = 0;
  transform.LookAt(_upVec);
//    transform.eulerAngles = _upVec;
}

最初我认为这是我的技能,但在花了一个月的时间后,我开始认为这是不可能做到的。但那不可能。我知道吸收很多,但这是一个如此简单的概念。

有什么想法吗?

编辑:我以为我会添加我的层次结构:

CameraRotator(带脚本的父级) - &gt; MainCamera(孩子)

CompassRotator(父母) - &gt;指南针(旋转父母的脚本的孩子)

1 个答案:

答案 0 :(得分:0)

我将通过以下方式执行此操作: Camara默认为0、0、0旋转 Screenshot

对象放置在相机默认位置的中心。

摄像机脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NewBehaviourScript : MonoBehaviour
{
    Camera m_MainCamera;
    // Start is called before the first frame update
    void Start()
    {
        // Disable the sleep timeout during gameplay. 
        // You can re-enable the timeout when menu screens are displayed as necessary. 
        Screen.sleepTimeout = SleepTimeout.NeverSleep;
        // Enable the gyroscope. 
        if (SystemInfo.supportsGyroscope)
        {
            Input.gyro.enabled = true;
        }
        m_MainCamera = Camera.main;
        m_MainCamera.enabled = true;
    }

    // Update is called once per frame
    void Update()
    {
        if (m_MainCamera.enabled)
        {
            // First - Grab the Gyro's orientation. 
            Quaternion tAttitude = Input.gyro.attitude;
            // The Device uses a 'left-hand' orientation, we need to transform it to 'right-hand'
            Quaternion tGyro = new Quaternion(tAttitude.x, tAttitude.y, -tAttitude.z, -tAttitude.w);

            // the gyro attitude is tilted towards the floor and upside-down reletive to what we want in unity.  
            // First Rotate the orientation up 90deg on the X Axis, then 180Deg on the Z to flip it right-side up. 
            Quaternion tRotation = Quaternion.Euler(-90f, 0, 0) * tGyro;
            tRotation = Quaternion.Euler(0, 0, 180f) * tRotation;

            // You can now apply this rotation to any unity camera!
            m_MainCamera.transform.localRotation = tRotation;
        }
    }
}

使用此脚本,无论如何我的对象总是面对南方。

如果您希望物体面向北,则只需将视图在Y轴上旋转180º作为最后旋转:

Quaternion tRotation = Quaternion.Euler(-90f, 0, 0) * tGyro;
tRotation = Quaternion.Euler(0, 0, 180f) * tRotation;
//Face NORTH:
tRotation = Quaternion.Euler(0,180f, 0) * tRotation;

希望这可能有帮助;)