【问题标题】:Sliders in Unity VRUnity VR 中的滑块
【发布时间】:2018-06-08 17:29:54
【问题描述】:

我们正在开发一款适用于 Go 的视频播放器应用。我们构建了一个简单的 raycaster 脚本,用于在用户指向 UI Button 元素并拉动触发器时触发 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 来更改该值,但这并不能真正给我们提供我们想要的滑动行为,只有在我们知道我们最终的位置后才能让我们设置新值。

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

【问题讨论】:

  • “但这并没有真正给我们提供我们想要的滑动行为,只有在我们知道我们结束的位置后才能让我们设置新值。”你能指望什么?您在 Slider 上寻找的行为是什么?
  • 具体来说,您可以指向它,握住扳机,然后来回滑动它。 :) 使用此代码,它根本不响应(因为它不是按钮)。
  • 您可以使用Silder.value 或Slider.onValueChanged 从代码中滑动滑块。不确定您遇到的确切问题是什么。
  • 对,您可以设置新值(释放触发器时您希望发生的情况),但这并不能说明跟踪滑块 - 让它跟随您所在的位置按住扳机时指向。
  • 嗨,肖恩,我刚刚发布的答案应该提供您所追求的。您可以使用 Oculus 为此编写的OVRInputModule。这也应该消除您在按钮上为“点击”设置自定义脚本的需要,因为OVRInputModule 也应该自动处理,如果设置如下面的答案。最后,我为指针和凝视指针添加了一条简单的线。如果需要,这些可以很容易地更改/删除。它们只是为了演示目的。

标签: c# unity3d virtual-reality


【解决方案1】:

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

为此,我将代码拆分为三个脚本; ControllerInfo、ControllerPointer 和 SetUITransformRay。

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

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 射线设置控制器。通常,您的场景中有两个控制器是必需的;一左一右。有关如何设置的更多信息,请参阅下面的完整方法。将此组件添加到您添加画布时生成的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 步)设置您的画布和事件系统。

在画布上,

在事件系统上,

步骤 3) 设置正确的对象

创建 3 个对象; Controller Manager、Controller Pointer 和 OVRGazePointer。

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

在控制器指针上,有一个LineRenderer。这有 两个 点,无论在哪里。它使用世界空间。它的宽度为 0.005。

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

【讨论】:

  • 一流的答案!谢谢你。我将深入研究 Oculus 代码(如果还没有的话,使其通用性足以支持我们使用的非 Oculus 平台)。
  • @SeanMcMains 很高兴我能帮上忙
【解决方案2】:

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

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

第二个是“基本 UI 场景”中的leap motion interaction engine。他们使用物理实现了滚动条,因此您可以用手与之交互。你可以检查一下,我认为它会非常有用。

【讨论】:

  • 感谢指点!在进一步研究之后,我认为最终编写或修改 InputModule 来做我们想做的事情(就像 Google 和 Leap 所做的那样)确实是我们最好的选择。我只是希望这将是一种足够普遍的方式,以至于有人已经完成了它并为我们节省了努力。 :)
【解决方案3】:

后来我发现这篇来自 Oculus 的博客文章提供了一些很棒的代码和示例;它与 Dan 的回答类似,但更全面,并带有可下载的示例。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-16
    • 2016-12-10
    • 2020-06-06
    • 2016-05-10
    • 1970-01-01
    • 1970-01-01
    • 2021-05-23
    • 1970-01-01
    相关资源
    最近更新 更多