Ориентация гарнитуры Oculus Quest при установке влияет на * некоторые * объекты в игре

В очень простой демонстрации Quest, созданной в Unity, у меня есть лазерная указка, прикрепленная к каждому контроллеру. (Указатель основан на этой серии видеороликов YouTube. Я добавил дополнительную лазерную указку к правому контроллеру.) Каждый указатель должен начинаться с позиции контроллера и распространяться на некоторое расстояние в прямом направлении контроллера.

Однако, если я использую Quest и запускаю демоверсию, не изменяя центр обзора моего Quest, я не вижу такого поведения. Вместо этого лазерные указки смещены как по положению, так и по вращению от контроллера. Иногда они начинают на 1 мировую единицу выше контроллеров. Иногда они уходят налево. Иногда они указывают на 45 градусов от прямого направления. Иногда сочетание всех трех. При запросе Unity сообщает, что начальное положение и поворот точно такие же, как у контроллеров - смещение не учитывается.

После запуска демонстрации движение лазерных указателей правильно отображается на перемещение контроллеров: и перемещение, и вращение правильно фиксируются. (Другие внутриигровые объекты вращаются вокруг вертикальной оси в зависимости от ориентации Oculus Home при запуске игры. Например, если меню находится справа от меня, когда я запускаю файл apk, то и кнопки в игре будут.)

Я не понимаю, что могло вызвать смещение при запуске и как его исправить. Я рад предоставить всю папку Unity Assets (без папки Oculus объемом 500 МБ) по запросу.


Pointer.cs (скрипт, отвечающий за создание лазерных указателей)

using UnityEngine;
using UnityEngine.EventSystems;

public class Pointer : MonoBehaviour
{
    [SerializeField] private float defaultLength = 5.0f;
    [SerializeField] private float startOffset = 0.05f;
    [SerializeField] private GameObject pointerTip = null; // Hard-coded to be PointerTip object associated with this pointer
    [SerializeField] private bool isRightPointer; // Hard-coded from inspector window

    public Camera Camera { get; private set; } = null;

    private LineRenderer lineRenderer = null;
    private InputModule_VR inputModule = null;

    private void Awake()
    {
        Camera = GetComponent<Camera>();

        lineRenderer = GetComponent<LineRenderer>();
    }

    private void Start()
    {
        Camera.enabled = false;
        // current.currentInputModule does not work
        inputModule = EventSystem.current.gameObject.GetComponent<InputModule_VR>();
    }

    private void Update()
    {
        UpdateLine();
    }

    private void UpdateLine()
    {
        // Use default or distance
        PointerEventData data = inputModule.Data;
        RaycastHit hit = CreateRaycast();

        // If nothing is hit, set to default length
        float colliderDistance = hit.distance == 0 ? defaultLength : hit.distance;
        float canvasDistance = data.pointerCurrentRaycast.distance == 0 ? defaultLength : data.pointerCurrentRaycast.distance;

        // Get the closer distance
        float targetLength = Mathf.Min(colliderDistance, canvasDistance);

        // Default
        Vector3 endPosition = transform.position + (transform.forward * targetLength);

        // Set position of the dot
        pointerTip.transform.position = endPosition;

        // Set the positions of the linerenderer
        Vector3 startPosition = this.transform.position + (this.transform.forward * startOffset) +
            (this.transform.up * -0.01f);
        if (isRightPointer)
        {
            startPosition += this.transform.right * 0.01f;
        }
        else
        {
            startPosition -= this.transform.right * 0.01f;
        }
        lineRenderer.SetPosition(0, startPosition);
        lineRenderer.SetPosition(1, endPosition);
    }

    private RaycastHit CreateRaycast()
    {
        RaycastHit hit;
        Ray ray = new Ray(transform.position, transform.forward);
        Physics.Raycast(ray, out hit, defaultLength);

        return hit;
    }
}

InputModule_VR.cs (скрипт, отвечающий за взаимодействие лучей с элементами интерфейса)

using UnityEngine;
using UnityEngine.EventSystems;

public class InputModule_VR : BaseInputModule
{
    private Camera pointerCamera = null;
    [SerializeField] private Pointer pointer = null;

    public PointerEventData Data { get; private set; } = null;

    protected override void Awake()
    {
        // Grab the camera we'll associate with all of our canvases
        pointerCamera = GameObject.Find("LeftHandPointer").GetComponent<Camera>();

        pointer = GameObject.Find("LeftHandPointer").GetComponent<Pointer>();
    }

    protected override void Start()
    {
        // Make sure every canvas knows to use the pointer camera for determining
        //   raycast hits
        Canvas[] canvases = FindObjectsOfType<Canvas>();
        foreach (Canvas canvas in canvases)
        {
            canvas.worldCamera = pointerCamera;
        }

        Data = new PointerEventData(eventSystem);
        Data.position = new Vector2(pointer.Camera.pixelWidth / 2, pointer.Camera.pixelHeight / 2);
    }

    public override void Process()
    {
        eventSystem.RaycastAll(Data, m_RaycastResultCache);
        Data.pointerCurrentRaycast = FindFirstRaycast(m_RaycastResultCache);

        HandlePointerExitAndEnter(Data, Data.pointerCurrentRaycast.gameObject);
    }

    public void Press()
    {
        Data.pointerPressRaycast = Data.pointerCurrentRaycast;

        Data.pointerPress = ExecuteEvents.GetEventHandler<IPointerClickHandler>(Data.pointerPressRaycast.gameObject);

        ExecuteEvents.Execute(Data.pointerPress, Data, ExecuteEvents.pointerDownHandler);
    }

    public void Release()
    {
        GameObject pointerRelease = ExecuteEvents.GetEventHandler<IPointerClickHandler>(Data.pointerCurrentRaycast.gameObject);

        if (Data.pointerPress == pointerRelease)
            ExecuteEvents.Execute(Data.pointerPress, Data, ExecuteEvents.pointerClickHandler);

        ExecuteEvents.Execute(Data.pointerPress, Data, ExecuteEvents.pointerUpHandler);

        Data.pointerPress = null;

        Data.pointerCurrentRaycast.Clear();
    }
}

0 ответов

Другие вопросы по тегам