Как определить направление просмотра телефонов Android при запуске приложения

#c# #android #unity3d

#c# #Android #unity-игровой движок

Вопрос:

Я работаю над приложением дополненной реальности для Android без отслеживания изображений / объектов. Пользователь занимает заранее определенную позицию, и виртуальные объекты помещаются в реальный мир. когда пользователь поворачивается или перемещает телефон, объекты фиксируются на своих соответствующих местах. Я делаю это, применяя данные гироскопа к камере.

Моя проблема: я хочу, чтобы позиции объектов всегда фиксировались в одних и тех же местах, независимо от направления просмотра пользователем при запуске приложения. Прямо сейчас, при запуске приложения, расположение объектов зависит от камеры. После этого они фиксируются на своих местах, когда пользователь меняет направление просмотра.

Я нарисовал изображение того, в чем именно заключается проблема, чтобы лучше проработать: изображение направления просмотра пользователем

Я хочу знать, какие датчики имеют отношение к решению этой проблемы. Поскольку Google Maps точно определяет направление просмотра пользователя, я предполагаю, что есть встроенные датчики, чтобы выяснить, в каком направлении смотрит пользователь, чтобы применить эту информацию к повороту камеры при запуске.

Это код, который я использую, чтобы применить поворот телефонов к камере (я использую Unity и C #):

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

public class Gyrotransform : MonoBehaviour
{
    // STATE
    private float _initialYAngle = 0f;
    private float _appliedGyroYAngle = 0f;
    private float _calibrationYAngle = 0f;
    private Transform _rawGyroRotation;
    private float _tempSmoothing;

    // SETTINGS
    [SerializeField] private float _smoothing = 0.1f;

    private IEnumerator Start()
    {
        Input.gyro.enabled = true;
        Application.targetFrameRate = 60;
        _initialYAngle = transform.eulerAngles.y;

        _rawGyroRotation = new GameObject("GyroRaw").transform;
       // _rawGyroRotation.parent = Core.Instance.transform;
        _rawGyroRotation.position = transform.position;
        _rawGyroRotation.rotation = transform.rotation;

        // Wait until gyro is active, then calibrate to reset starting rotation.
        yield return new WaitForSeconds(1);

        StartCoroutine(CalibrateYAngle());
    }

    private void Update()
    {
        ApplyGyroRotation();
        ApplyCalibration();

        transform.rotation = Quaternion.Slerp(transform.rotation, _rawGyroRotation.rotation, _smoothing);
    }

    private IEnumerator CalibrateYAngle()
    {
        _tempSmoothing = _smoothing;
        _smoothing = 1;
        _calibrationYAngle = _appliedGyroYAngle - _initialYAngle; // Offsets the y angle in case it wasn't 0 at edit time.
        yield return null;
        _smoothing = _tempSmoothing;
    }

    private void ApplyGyroRotation()
    {
        _rawGyroRotation.rotation = Input.gyro.attitude;
        _rawGyroRotation.Rotate(0f, 0f, 180f, Space.Self); // Swap "handedness" of quaternion from gyro.
        _rawGyroRotation.Rotate(90f, 180f, 0f, Space.World); // Rotate to make sense as a camera pointing out the back of your device.
        _appliedGyroYAngle = _rawGyroRotation.eulerAngles.y; // Save the angle around y axis for use in calibration.
    }

    private void ApplyCalibration()
    {
        _rawGyroRotation.Rotate(0f, -_calibrationYAngle, 0f, Space.World); // Rotates y angle back however much it deviated when calibrationYAngle was saved.
    }

    public void SetEnabled(bool value)
    {
        enabled = true;
        StartCoroutine(CalibrateYAngle());
    }
}  

Ответ №1:

Насколько я понимаю, Gyroskope возвращает разницу во вращении с момента ее запуска.

Вот почему ваши объекты отображаются в том направлении, в котором вы смотрите во время запуска.


Я предполагаю, что вам скорее нужен Compass.magneticHeading, по крайней мере, для настройки правильного поворота один раз при запуске игры

  // Orient an object to point to magnetic north.
transform.rotation = Quaternion.Euler(0, -Input.compass.magneticHeading, 0);
  

Вы могли бы сделать это один раз при запуске для родительского элемента всех объектов, которые вы хотите отобразить, чтобы правильно сориентировать их на север по GPS.