Unity VR 中的滑块

Sliders in Unity VR

我们正在为 Go 开发视频播放器应用程序。我们构建了一个简单的 raycaster 脚本来在用户指向 UI 按钮元素并拉动触发器时触发 onClick 事件:

bool triggerPulled = OVRInput.GetDown(OVRInput.Button.PrimaryIndexTrigger);
    if (Physics.Raycast(transform.position, transform.forward, out hit, 1000))
    {

        if ( triggerPulled )
        {

            // if we hit a button
            Button button = hit.transform.gameObject.GetComponent<Button>();

            if (button != null)
            {
                button.onClick.Invoke();
            }

        }
....
    }

我们非常希望能够使用激光指示器和按钮来操纵 UI 滑块,但不清楚是否存在我们可以触发的类似事件以实现适当的行为。我们可以调用 onValueChanged 来更改值,但这并不能真正为我们提供我们想要的滑动行为,只有在我们知道结束位置后才能让我们设置新值。

有人对如何解决这个问题有好的想法吗?

我不知道这是否有帮助,但我强烈建议检查这两个 sdks:

第一个是 GoogleVR sdk,您可以查看那里的事件系统以及他们如何实现他们的 raycast 系统并将其与 unity 集成。

第二个是leap motion interaction engine在"Basic UI scene"。他们使用物理学实现了滚动条,因此您可以用手与之交互。你可以看看我认为它会很有用。

Oculus Integration 有一个名为 OVRInputModule.cs 的脚本。我相信这是为您正在尝试做的事情而设计的。为了做到这一点,有几个步骤。结果的 GIF。

为此,我将代码拆分为三个脚本; ControllerInfoControllerPointerSetUITransformRay

控制器信息只是一个 class,可确保脚本始终具有正确的信息。

using UnityEngine;
using static OVRInput;

public class ControllerInfo : MonoBehaviour {
    [SerializeField]
    private Transform trackingSpace;
    public static Transform TRACKING_SPACE;
    public static Controller CONTROLLER;
    public static GameObject CONTROLLER_DATA_FOR_RAYS;

    private void Start () {
        TRACKING_SPACE = trackingSpace;
    }

    private void Update()
    {
        CONTROLLER = ((GetConnectedControllers() & (Controller.LTrackedRemote | Controller.RTrackedRemote) & Controller.LTrackedRemote) != Controller.None) ? Controller.LTrackedRemote : Controller.RTrackedRemote;
    }
}

ControllerPointer 从控制器画一条线。这表示控制器指向的方式。将此添加到 LineRenderer.

using UnityEngine;
using UnityEngine.EventSystems;
using static OVRInput;

[RequireComponent(typeof(LineRenderer))]
public class ControllerPointer : MonoBehaviour
{
    [SerializeField]
    private SetUITransformRay uiRays;
    private LineRenderer pointerLine;
    private GameObject tempPointerVals;

    private void Start()
    {
        tempPointerVals = new GameObject();
        tempPointerVals.transform.parent = transform;
        tempPointerVals.name = "tempPointerVals";
        pointerLine = gameObject.GetComponent<LineRenderer>();
        pointerLine.useWorldSpace = true;

        ControllerInfo.CONTROLLER_DATA_FOR_RAYS = tempPointerVals;
        uiRays.SetUIRays();
    }

    private void LateUpdate()
    {
        Quaternion rotation = GetLocalControllerRotation(ControllerInfo.CONTROLLER);
        Vector3 position = GetLocalControllerPosition(ControllerInfo.CONTROLLER);
        Vector3 pointerOrigin = ControllerInfo.TRACKING_SPACE.position + position;
        Vector3 pointerProjectedOrientation = ControllerInfo.TRACKING_SPACE.position + (rotation * Vector3.forward);
        PointerEventData pointerData = new PointerEventData(EventSystem.current);
        Vector3 pointerDrawStart = pointerOrigin - pointerProjectedOrientation * 0.05f;
        Vector3 pointerDrawEnd = pointerOrigin + pointerProjectedOrientation * 500.0f;
        pointerLine.SetPosition(0, pointerDrawStart);
        pointerLine.SetPosition(1, pointerDrawEnd);

        tempPointerVals.transform.position = pointerDrawStart;
        tempPointerVals.transform.rotation = rotation;
    }
}

SetUITransformRay 将自动为 OVRInputModule 射线设置控制器。这是必需的,因为通常您的场景中有两个控制器;一左一右。有关如何设置的更多信息,请参阅下面的完整方法。将此组件添加到您添加 canvas.

时生成的 EventSystem
using UnityEngine;
using UnityEngine.EventSystems;

public class SetUITransformRay : MonoBehaviour
{
    [SerializeField]
    private OVRInputModule inputModule;
    [SerializeField]
    private OVRGazePointer gazePointer;

    public void SetUIRays()
    {
        inputModule.rayTransform = ControllerInfo.CONTROLLER_DATA_FOR_RAYS.transform;
        gazePointer.rayTransform = ControllerInfo.CONTROLLER_DATA_FOR_RAYS.transform;
    }
}

使用步骤

步骤 1) 场景设置

导入 Oculus 集成包。将 OVRCameraRig 拖到您的场景中。将 OVRTrackedRemote 拖入左右锚点。根据锚点将每个遥控器设置为左侧或右侧。

步骤 2) 设置您的 canvas 和事件系统。

在Canvas,

在事件系统上,

步骤 3) 设置正确的对象

创建3个对象; Controller ManagerController PointerOVRGazePointer

对于OVRGazePointer,我只是快速进入了UI、Oculus\VR\Scenes的示例场景,并在那里预制了OVRGazePointer

控制器指针上有一个LineRenderer。这有两个点,不管在哪里。它 使用世界 space。它的宽度为 0.005.

只有两点,使用世界space非常重要。这是因为 ControllerPointer 脚本依赖于这两个设置。

后来我从 Oculus 找到了这个博客 post,它提供了一些很棒的代码和示例;它与 Dan 的回答类似,但更详尽并且有可下载的示例。

https://developer.oculus.com/blog/easy-controller-selection/