大家好,又见面了,我是你们的朋友全栈君。
文档目录
- Introduction
- 1 Quickstart(快速开始)
- 1.1 Download(下载插件)
- 1.2 SteamVR Input Window(输入窗口)
- 1.3 Copy JSONs(复制 JSON)
- 1.4 Save and Generate(保存并生成)
- 1.5 Interaction System(交互系统)
- 2 Render Models(渲染模式)
- 2.1 The Component(组件)
- 2.2 Attaching Objects(附着对象)
- 2.3 Notes(注意)
- 3 SteamVR Input(输入系统)
- 3.1 Boolean 类型
- 3.2 Single 类型
- 3.3 Vector2 类型
- 3.4 Vector3 类型
- 3.5 Pose 类型
- 3.6 Skeleton 类型
- 3.7 Vibration 类型
- 3.8 Using actions(动作使用)
- 3.9 New action sets(新建动作集)
- 4 Skeleton Input(骨骼输入)
- 4.1 Range Of Motion(运动范围)
- 4.2 Skeletal Transform Space(骨骼变换空间)
- 4.3 Finger Curls(手指弯曲)
- 4.3 Finger Splays(手指伸展)
- 4.4 Skeletal Tracking Level(骨骼跟踪级别)
- 4.5 SteamVR_Behaviour_Skeleton
- 4.6 SteamVR_Behaviour_Skeleton Events
- 5 Interaction System(交互系统)
- 5.1 Getting started(入门指南)
- 5.2 Sample scene(示例场景)
- 5.3 Documentation(文件)
- 5.3.1 Core
- 5.3.2 Player
- 5.3.3 Hand
- 5.3.4 Interactable
- 5.3.5 Throwable
- 5.3.6 LinearDrive
- 5.3.7 CircularDrive
- 5.3.8 LinearMapping
- 5.3.9 VelocityEstimator
- 5.3.10 IgnoreHovering
- 5.3.11 UIElement
- 5.3.12 ItemPackage
- 5.3.13 ItemPackageSpawner
- 5.3.14 ItemPackageReference
- 5.3.15 PlaySound
- 5.3.16 SoundPlayOneShot
- 5.3.17 Util
- 5.3.18 InteractableHoverEvents
- 5.3.19 InteractableButtonEvents
- 5.3.20 ComplexThrowable
- 5.3.21 DistanceHaptics
- 5.3.22 Player (Prefab)
- 5.3.23 BlankController (Prefab)
- 5.4 Teleport(传送)
- 5.4.1 Teleport
- 5.4.2 TeleportMarkerBase
- 5.4.3 TeleportArea
- 5.4.4 TeleportPoint
- 5.4.5 TeleportArc
- 5.4.6 AllowTeleportWhileAttachedToHand
- 5.4.7 IgnoreTeleportTrace
- 5.4.8 Teleporting (Prefab)
- 5.4.9 TeleportPoint (Prefab)
- 5.5 Render Model(渲染模型)
- 5.5.1 Hints
- 5.5.2 ControllerButtonHints
- 5.5.3 Longbow
- 5.5.3.1 Longbow.cs
- 5.5.3.2 ArrowHand.cs
- 5.5.3.3 Arrow.cs
- 5.5.3.4 ArrowheadRotation.cs
- 5.5.3.5 SoundBowClick
- 5.5.3.6 ArcheryTarget.cs
- 5.5.3.7 FireSource.cs
- 5.5.3.8 ExplosionWobble.cs
- 5.5.3.9 Balloon.cs
- 5.5.3.10 BalloonColliders.cs
- 5.5.3.11 BalloonHapticBump.cs
- 5.5.3.12 BalloonSpawner.cs
- 5.6 Samples(示例)
- 5.6.1 ControllerHintsExample
- 5.6.2 InteractableExample
- 6 Skeleton Poser(骨骼姿态)
- 6.1 The Basics(基本需求)
- 6.2 Using the Skeleton Poser with the SteamVR Interaction system(将 Skeleton Poser 与 SteamVR 交互系统结合使用)
- 6.3 Pose Editor(姿态编辑器)
- 6.4 Blending Editor(混合编辑器)
- 6.5 Manual Behaviours(手动行为)
- 6.6 Scaling(缩放)
- 7 文档更新记录
- 8 小结
Introduction
本文基于 SteamVR 插件的开发文档翻译并总结 SteamVR 开发过程中的基本用法。本文总结汇总了 SteamVR 插件文档的内容,对文档部分内容进行了删减。目前仅仅只是翻译并结合部分内容进行补充,部分内容可能存在纰漏,后续会结合开发过程逐步更新修改此文章的内容。 插件文档地址:https://valvesoftware.github.io/steamvr_unity_plugin/articles/intro.html
设备 | 版本 |
---|---|
Unity | 2019.1.2.f1 |
SteamVR Plugin | V2.7.3 |
HMD | HTC VIVE Pro 2.0 |
1 Quickstart(快速开始)
1.1 Download(下载插件)
插件下载有很多方式,可以前往 Steam 平台下载,也可以在 Unity Asset Store 搜索 Steam VR 进行下载。 Steam:https://store.steampowered.com/app/250820/SteamVR/ Unity Asset Store:https://assetstore.unity.com/packages/tools/integration/steamvr-plugin-32647 安装教程详情参考:https://blog.csdn.net/xiaofeiyu321/article/details/120163304?spm=1001.2014.3001.5501
1.2 SteamVR Input Window(输入窗口)
在 Unity 中导入 Steam VR 插件,导入完成后可以在 Window 菜单栏中打开 Steam VR 的输入窗口。
1.3 Copy JSONs(复制 JSON)
单击确定复制默认的 “SteamVR Input JSON” 文件。 这些 actions(动作)和 binding(绑定)将帮助交互系统工作,并为您提供如何开始的示例。
在打开SteamVR Input 窗口的过程中,插件会检测项目中是否存在 actions.json 文件,该文件存储了项目中动作(Action)与动作集(Action Sets)的信息,在打开SteamVR Input窗口时会读取该文件。如果没有 actions.json,插件会建议使用默认提供的示例文件
点击 Yes 后,会生成默认的与输入有关的 json 配置文件:
插件会将示例文件 actions.json 以及一些当前主流控制器的按键绑定配置文件拷贝到项目中的 StreamingAssets/SteamVR 下,在之后程序运行时,也将从此文件夹中读取用户关于动作(action)的配置信息。
1.4 Save and Generate(保存并生成)
拷贝上述 Json 文件并打开窗口后,点击底部的 “保存并生成” 按钮。 这将保存您的操作并生成一些类来初始化它们,并使您可以在编辑器中和通过代码轻松访问它们。
在窗口中有四个 Action Sets(动作集)以及动作集包含的 Actions(动作),我们可以在面板中根据需求自定义动作集(添加自己的动作集或者删除原有动作集的内容)。
我们自定义完成动作的设置后,可以点击 Open binding UI 就可以对动作进行绑定。
当点击 Save and Generate 按钮后,插件将为动作以及动作集生成可编程访问的对象类,将它们放置在项目的 SteamVR_Input 目录下。
1.5 Interaction System(交互系统)
完成上述操作后,打开 “交互系统” 示例场景,我们可以在 Assets/SteamVR/InteractionSystem/Samples/Interaction_Example 找到示例场景。
然后连接头盔,控制器等设备,点击 Unity 的播放,开始探索 “交互系统” 的示例场景。 注:示例场景中包含很多常用的功能,在日后的开发过程中,可能需要实现类似示例场景中的功能。例如,利用射线实现 UI 交互、利用手柄抓握物体、传送等。可以多体验一下示例场景,学习相关功能的实现。
2 Render Models(渲染模式)
由于沉浸在虚拟现实中时您的整个视野都会被覆盖,因此拥有您所握持的控制器的虚拟表示会很有帮助。SteamVR 提供了一种简单的方法,不仅可以获取通用控制器模型,还可以获取具有单独驱动组件的模型。 因此,当您在现实生活中扣动控制器上的扳机时,您也可以在虚拟世界中看到它也在拉动。 这有助于提高可用性并有力地促进存在感。
2.1 The Component(组件)
交互系统和简单示例场景都有使用渲染模型的装备。 在 [Camera Rig] 预制件的 Simple Sample 场景中,您将找到Controller (left)和Controller (right)。 这些游戏对象上有一个SteamVR_Behaviour_Pose组件,用于设置变换的位置和旋转。
在这些对象下,您将看到名为Model的 GameObjects,其中包含我们的SteamVR_RenderModel组件。 它有几个成员:
- Index 索引:这是控制器的 “跟踪设备索引”。 它是渲染模型系统用来向底层系统标识控制器的整数 id。 在之前的 SteamVR 迭代中,这也用于访问该控制器上的输入,但现在这是通过 “输入系统” 完成的。
- Model Override 模型覆盖:通常出于测试目的,您可以指定要显示的模型,而不是动态评估连接的设备类型。
- Shader 着色器:如果您更喜欢使用不同的着色器来渲染模型,您可以在此处指定它。 默认情况下,使用 Unity 的标准着色器。
- Verbose 详细:将输出调试日志以告诉您脚本发生了什么。
- Create Components 创建组件:在勾选的情况下为每个组件创建单独的游戏对象。
- Update Dynamically 动态更新:将移动单个组件与其物理对应物内联。
2.2 Attaching Objects(附着对象)
开发人员通常希望将游戏对象附加到控制器上的特定点。 为此,我们在控制器的每个部分下放置了一个名为 “attach” 的游戏对象,该部分以相关部分为中心。 为便于访问,您可以访问SteamVR_RenderModel脚本并调用GetComponentTransform(string componentName),它将返回 a Transform(不进行任何 GC 分配)。 此处的 componentName 参数区分大小写,因此请确保传入的组件名称与运行时在 Hierarchy 视图中显示的完全相同。
2.3 Notes(注意)
SteamVR_RenderModel组件需要与设置其索引的对象位于同一游戏对象上。 在[CameraRig]预制件中,这是由SteamVR_Behaviour_Pose脚本完成的。
3 SteamVR Input(输入系统)
SteamVR Unity 插件的核心是 action(动作)。 虚拟现实正在快速发展,我们需要我们的软件能够与硬件一起发展。 SteamVR 输入将代码的设备特定部分抽象化,因此您可以专注于用户的意图 – 他们的 action(动作)。 而不是编写代码来识别 “将 Trigger 按钮下拉 75% 的方式来抓取块”,您现在可以只关注最后一点, “抓住块”。 您仍然可以为 “抓取” 的含义配置默认值,但用户可以在标准界面中将其重新绑定到他们设定的偏好(首选项)。 当新的输入设备出现时,您的用户可以发布绑定以共享该设备,而无需更改代码。
Input System 与之前处理用户输入有显著的不同,使用 SteamVR Input System,开发人员可以在应用程序之外定义默认的动作并与按键进行绑定,而不需要将输入视为某一特定设备的特定按键。这样新的设备可以快速适配应用程序,无需更改代码。比如,当开发者检测玩家是否抓取某个物体的时候,不是检测 Vive 控制器的 Trigger 键或 Oculus Touch 控制器的 Grip 键是否被按下,而是检测预定义的 “Grab” 动作是否为 True 即可。作为开发者,可以在 SteamVR 中为 Grab 动作设置默认按键和阈值,当程序运行时,也可修改这些数值以满足玩家的个人偏好。基于这种机制,不光能够解决控制器碎片化的问题,也可以快速适配未来发布的设备。
action(动作):程序中定义的用户行为,例如:传送、左右转动等。我们可以将这些动作与不同设备手柄的按键进行绑定。 开发过程中,我们只需要定义好用户可执行的动作,使用不同设备的用户只需要在手柄设置面板中自定义动作与按键的绑定就可以使用我们开发的程序了。 也即不需要重新编写代码,只需在设置面板更改动作的绑定。
[核心]:关注动作而不是按键本身!因为不同设备按键不同,但对于应用只需知道动作而不用在意按键。这样就能使得开发者在编程中专注于用户的动作,而不是具体的控制器按键。
这种抽象输入的风格与许多其他公司正在考虑的类似。 大多数主要虚拟现实硬件公司的成员都加入了 Khronos,创建了仍在开发中的 OpenXR 标准。(OpenXR 是一套标准接口,它介于设备生产商与内容制作之间。)
SteamVR 将动作分为 6 种不同类型的输入和一种输出类型:
- Boolean – true or false
- Single – an analog value
- Vector2 – two analog values
- Vector3 – three analog values
- Pose– position, rotation, velocity, and angular velocity(位置、旋转、速度和角速度)
- Skeleton – Orientations for each bone in a hand(手中每根骨头的方向)
- Vibration – Actuating haptic motors(驱动触觉电机——震动输出)
3.1 Boolean 类型
Boolean 类型的动作是 True 或 False 的值。 例如,Grab 是一个常见的动作,要么为真,要么为假。 要么打算抓取某物,要么不抓取,不存在中间状态。 对于 Vive Wand,这可能意味着将扳机扣动 75%,对于 Oculus Touch,这可能意味着将手柄扳机扣动 25%,对于 Knuckles,这可能是电容感应和力感应的某种组合。 但最终它分解为真值或假值。在 Unity 中对应类为SteamVR_Action_Boolean,通常用于按钮动作。
3.2 Single 类型
Single 类型的动作是从 0 到 1 的模拟值,类似于浮点型(float)。在这些场景中,您需要更多数据而不仅仅是真或假。 这些比您预期的要少。 如果之前您正在读取 0 到 1 的值,然后等待它达到某个点,即阈值,那么您可以使用布尔操作完成相同的操作,从而使您的最终用户更容易进行自定义。 单个动作的一个很好的例子是 SteamVR 交互系统中遥控车的油门。 您作为用户所采取的动作可能因您希望汽车行驶的速度而异。在 Unity 中对应类为SteamVR_Action_Single,常用于获取 Trigger 键的键程值。
3.3 Vector2 类型
Vector2 类型的动作是两个模拟值的组合,是二维数据。 一般在 VR 中,这类动作最好通过径向菜单或 2D 定位来表示。 在 SteamVR 交互系统中,我们有一个驾驶遥控车和游戏平台(platformer)类型角色的示例。 在 Vive Wand 上,它映射到触摸板,但在 Oculus Touch 和 Knuckles 上,它映射到操纵杆。 对于遥控车,我们使用 y 轴来确定向前或向后的方向,使用 x 轴来确定转弯。 使用游戏平台(platformer),我们将 x/y 输入映射到角色移动的方向和幅度。在 Unity 中对应类为SteamVR_Action_Vector2,与 Unity 或 C# 中的 Vector2 类型相似,常用于获取 Trackpad 上手指接触点坐标。
3.4 Vector3 类型
Vector3 类型的动作不常用,是三维数据,有 3 个数据成员。 在 SteamVR Home 中,这用于滚动,x、y 和 z 是要滚动的页面数量。在 Unity 中对应类为SteamVR_Action_Vector3。
3.5 Pose 类型
Pose 类型的动作表示三维空间中位置和旋转,一般用于跟踪 VR 控制器。 用户可以通过在控制器上设置姿势代表的点来自定义这些绑定。 一些用户可能会发现稍微不同的跟踪位置或旋转对他们来说感觉更好。在 Unity 中对应类为SteamVR_Action_Pose,用于获取手柄控制器的运动数据。
3.6 Skeleton 类型
Skeleton 类型的动作使用 SteamVR 骨骼输入来获得我们对握住 VR 控制器时手指方向的最佳估计。这种类型的动作能够获取用户在持握手柄控制器时的手指关节数据,通过返回数据,结合手部渲染模型,能够更加真实的呈现手部在虚拟世界的姿态,虽然不及像 LeapMotion 等设备获取手指输入那样精确,但是足以获得良好的沉浸感。在 Unity 中对应类为SteamVR_Action_Skeleton(提供用于呈现手部模型的骨骼数据,每个关节点的位置和旋转)。
3.7 Vibration 类型
Vibration 类型的动作用于触发 VR 设备上的触觉反馈。 这可以是控制器、背心,甚至是椅子。
3.8 Using actions(动作使用)
创建动作后,您可以在自己的脚本中使用它们,也可以使用我们创建的用于处理一些常见任务的统一组件。 它们被命名为 SteamVR_Action_Boolean、SteamVR_Action_Single、SteamVR_Action_Vector2、SteamVR_Action_Vector3、SteamVR_Action_Pose和SteamVR_Action_Skeleton。 将它们拖到 GameObject 上以查看它们可以做什么。
我们可以在 C# 脚本中定义对应类型的动作(具体代码参照后面文件所示):
将脚本挂载到物体身上,在 Inspector 面板中可以给定义的动作进行赋值:
动作的完整路径参照 action.json 文件中所示:
也可以通过代码直接获取动作,获取动作的方法有很多种(可以参照 SteamVR 插件的 API 文档),如下图所示:
代码语言:javascript复制//通过该动作的完整路径获取动作--/actions/[actionSet]/[direction]/[actionName]
//动作的路径参照上图--/actions/default/in/InteractUI
//T--期望返回的动作类型,actionName--动作的名字,caseSensitive--检索时是否区分大小写
public static T GetAction<T>(string actionName, bool caseSensitive = false)
public static SteamVR_Action_Single GetSingleAction(string actionName, bool caseSensitive = false)
代码如下图所示,可以通过这两种方式指定动作:
赋值后运行程序,在 Inspector 面板中可以看到已经赋好的值:
创建动作之后,可以进行动作测试。打开 SteamVR Input Live View 窗口,可以看到动作的触发情况:
红色代表动作未绑定按键,绿色代表就是触发了的 action(动作):
获取手柄输入,利用代码获取手柄的输入:
代码语言:javascript复制//如果 action(state)当前值为 true,则返回 true--返回当前动作的状态,检测按键是否一直被按住
//传入 SteamVR_Input_Sources
public bool GetState(SteamVR_Input_Sources inputSource)
代码语言:javascript复制//如果 action 的值在最近的更新中已更改为 true(从 false),则返回 true--按下按键
//传入 SteamVR_Input_Sources
public bool GetStateDown(SteamVR_Input_Sources inputSource)
代码语言:javascript复制//如果 action 的值在最近的更新中已更改为 false(从 true),则返回 true--松开按键
//传入 SteamVR_Input_Sources
public bool GetStateUp(SteamVR_Input_Sources inputSource)
SteamVR_Input_Sources 输入源:方法传入参数类型:
代码示例:
代码语言:javascript复制private void Update()
{
if (Boolean_Action.GetState(SteamVR_Input_Sources.Any))
{
Debug.Log("正在按扳机键!");
}
}
代码语言:javascript复制private void Update()
{
if (Boolean_Action.GetStateDown(SteamVR_Input_Sources.RightHand))
{
Debug.Log("右手扳机键被按下!");
}
if (Boolean_Action.GetStateUp(SteamVR_Input_Sources.RightHand))
{
Debug.Log("右手扳机键被松开");
}
}
完整代码如下所示:
代码语言:javascript复制using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Valve.VR;
public class ActionDemo : MonoBehaviour
{
public SteamVR_Action_Boolean Boolean_Action;
public SteamVR_Action_Single Single_Action;
public SteamVR_Action_Vector2 Vector2_Action;
public SteamVR_Action_Vector3 Vector3_Action;
public SteamVR_Action_Pose Pose_Action;
public SteamVR_Action_Skeleton Skeleton_Action;
private void Start()
{
Boolean_Action = SteamVR_Input.GetAction<SteamVR_Action_Boolean>("InteractUI");
Single_Action = SteamVR_Input.GetSingleAction("Squeeze");
}
private void Update()
{
//if (Boolean_Action.GetState(SteamVR_Input_Sources.Any))
//{
// Debug.Log("正在按扳机键!");
//}
if (Boolean_Action.GetStateDown(SteamVR_Input_Sources.RightHand))
{
Debug.Log("右手扳机键被按下!");
}
if (Boolean_Action.GetStateUp(SteamVR_Input_Sources.RightHand))
{
Debug.Log("右手扳机键被松开");
}
}
}
3.9 New action sets(新建动作集)
在开发过程中,我们经常需要根据项目需求定制化相应的动作集。新建动作集可以通过 SteamVR Input 面板进行设置:
通过点击 SteamVR Input 面板中 Action Sets 的 “ ” 号我们可以新建一个动作集:
在新建的动作集下方的下拉菜单中,我们可以设置该动作集在动作绑定界面的形式:
- per hand:单个设置,用户需每个控制器单独设置绑定
- mirrored:在动作绑定界面提供镜像模式的复选框,勾选后,仅需对一个控制器进行绑定,该控制器的绑定会映射到另一个
- hidden:该动作集不会在动作绑定界面显示
通过 Actions 下的 “ ” 号我们可以为新建的动作集添加动作:
其中,Type 也即我们上文提到的动作类型。面板中的 Required 用于设置该动作在动作绑定界面中的提示方式:
- optional:可选,指该动作用户可以选择绑定或者不绑定,这种动作在界面中不会进行提示
- suggested:建议,建议对该动作进行绑定,对部分特定程序可能会有影响
- mandatory:强制的,强制要求用户绑定该动作,不绑定该动作影响程序的使用
这几种提示方式在我们开发过程中,可以针对项目各个动作进行要求,以便用户更好地进行动作的绑定。面板中的 Localized String(本地化的字符串),用以设置该动作在绑定界面的显示文本。
动作集中的动作添加完毕后,点击 Save and generate,保存并生成。之后,我们就可以通过点击 Open binding UI 进入动作绑定界面:
在动作绑定界面,我们新建的动作集提示存在动作未绑定,我们需要对动作集中的动作进行绑定。提示文本即我们在前面设置的 Localized String。镜像模式即我们在创建动作集时下拉菜单里的 mirrored。
之后我们便可以根据我们动作的类型进行按键的绑定,选择不同的按键进行设置。绑定完成后需要点击设置位置下的 “√” 进行保存更改。
4 Skeleton Input(骨骼输入)
在 VR 中看到你的物理控制器很好,但人们真正想要的是能够看到他们的手。 随着 VR 控制器的进步,我们看到了截然不同的功能。 一些控制器只能按下按钮(无触摸),有些控制器甚至在半空中也能给出良好的手指估计,我们开始看到手套和相机具有完整的每个关节位置/旋转跟踪。 SteamVR Skeleton Input 为您提供了一个 API 来获取所有这些不同类型设备的每个关节数据。 对于数据较少的设备,我们根据按下的按钮估计手指位置,而对于更高级的控制器,数据只是通过。
4.1 Range Of Motion(运动范围)
我们有两个运动范围可供您获取骨骼数据。 如果您正在寻找精确到真实世界的数据,您可以使用WithController运动范围。 这意味着我们会在控制器允许的范围内尽可能地估计您的手指在现实世界中的位置。WithoutController为您提供从手指张开的扁平手到握成拳头的全方位范围。
With Controller | Without Controller |
---|---|
4.2 Skeletal Transform Space(骨骼变换空间)
根据您使用此数据的用例,您可能希望获得相对于不同事物的位置和旋转。 默认情况下,我们获得相对于它们的父级的位置和旋转。 但是您也可以相对于模型获取它们。
4.3 Finger Curls(手指弯曲)
对于某些事情,访问手指卷曲程度的概要可能更有用,而不是每个手指上 4 个关节的位置和旋转。 这些值的范围从 0 到 1,其中 1 表示完全卷曲。 您可以在skeletonAction.fingerCurls[]以数组的形式访问curl信息,或者在skeletonAction.indexCurl、skeletonAction.middleCurl、skeletonAction.RingCurl、skeletonAction.pinkyCurl和skeletonAction.thumbCurl中单独命名。
4.3 Finger Splays(手指伸展)
了解手指之间的间隙也是一个常用的信息。 为此,我们以与 Curls(弯曲)类似的方式提供数据。 从 0 到 1 的范围表示手指之间的间隙大小。skeletonAction.fingerSplays[]作为数组,或单独命名为skeletonAction.thumbIndexSplay、indexMiddleSplay、middleRingSplay和ringPinkySplay。
4.4 Skeletal Tracking Level(骨骼跟踪级别)
不同的控制器具有不同的能力来跟踪手指的各个关节。 在这里,我们提供了一个概览值,可以让您大致了解当前控制器的保真度级别。
- Estimated 预估:设备无法直接确定身体部位的位置。 设备提供的任何骨骼姿势都是根据活动按钮、触发器、操纵杆或其他输入传感器估计的。 示例包括 Vive 控制器和游戏手柄。
- Partial 局部:可以直接测量身体部位的位置,但自由度比实际身体部位少。设备可能无法测量某些身体部位的位置,而是根据其他输入数据进行估计。示例包括仅测量手指卷曲度的指关节或手套。
- Full 完整:可以在身体部位的整个运动范围内直接测量身体部位的位置。示例包括高端动作捕捉系统或测量每个手指节段旋转的手套。
4.5 SteamVR_Behaviour_Skeleton
骨骼行为(skeleton behaviour)是一个组件,它使 unity 中常见的Skeleton Input任务变得更容易。 通过设置skeletonAction和inputSource你可以让行为为你做很多工作。
- updatePose:将此设置为 true 将在每次更新骨骼时在您的游戏空间中定位游戏对象。
- mirroring:如果此骨骼数据应跨 x 轴镜像。
- SetRangeOfMotion(EVRSkeletalMotionRange newRangeOfMotion, float blendOverSeconds = 0.1f):为您提供一种简单的方法来混合一个新的运动范围。
- BlendToSkeleton(float overTime = 0.1f):完全混合以使用骨骼数据为骨骼设置动画。
- BlendToPoser(SteamVR_Skeleton_Poser poser, float overTime = 0.1f):完全混合以使用 Poser 为骨骼设置动画。
- BlendToAnimation(float overTime = 0.1f):完全混合到预定义的 Unity 动画。
- BlendTo(float blendToAmount, float overTime):允许您指定 poser/animation(姿势器/动画)数据和 skeleton input(骨骼输入)数据之间的混合程度。
- Transform GetBone(int joint):通过关节索引 (SteamVR_Skeleton_JointIndexes) 返回特定骨骼的变换(Transform)。
- ForceToReferencePose(EVRSkeletalReferencePose referencePose):强制骨骼进入 SteamVR 定义的特定参考姿势。 一般用于调试目的。
- Vector3[] GetBonePositions():提供一个数组,其中包含请求的空间中的所有骨骼位置。
- Quaternion[] GetBoneRotations():提供一个数组,其中包含请求的空间中所有骨骼旋转。
4.6 SteamVR_Behaviour_Skeleton Events
有两种形式的骨骼行为(skeleton behaviour)有五个有用的事件。 您可以订阅 unity 事件或更传统的 C# 事件。 C# 事件的好处是大多数 IDE 会根据事件类型自动为您创建一个带有命名参数的函数。
- onBoneTransformsUpdated:在更新了骨转换之后,将会触发。
- onTransformUpdated:在更新了根转换之后,将触发。
- onTransformChanged:根变换更改后,将触发(移动/旋转)。
- onConnectedChanged:当设备连接或断开时,执行此动作。
- onTrackingChanged:每当此设备的跟踪状态发生更改时执行。
5 Interaction System(交互系统)
Valve 发布 The Lab 后,我们从该项目中汲取了经验,并创建了一个交互系统,其他人可以在他们自己的项目中使用。 此系统已更新为使用 SteamVR 输入和新的 SteamVR 骨骼输入系统。 该系统可以作为如何使用这些新系统的示例。 它包括以下示例:
- Interaction with Unity UI elements:与 Unity UI 元素的交互
- Pickup, Drop, and Throw:拾起,放下,扔出去
- Multiple variations on throwing velocities:投掷速度的多种变化
- Bow and Arrow:弓和箭
- Wheel interactions:轮交互
- Proximity button:邻近按钮
- Variety of Skeleton Input examples:各种骨骼输入示例
- Teleporting:传送
- Using held objects:使用抓握对象
- Using Skeleton Input to form a hand around a held object:使用骨骼输入在手持物体周围形成一只手
5.1 Getting started(入门指南)
- 创建新场景
- 删除 “Main Camera” 对象(不删除主相机的话。看到的是主相机的画面,而不能看到 VR 相机的画面。)
- 将 “Player” 预制件从 Assets/SteamVR/InteractionSystem/Core/Prefabs 拖入场景中。 这个预制件设置了主要的 Player 组件和手。 它还与所需的所有相关 SteamVR 输入操作挂钩。
- 拖入后就能够在头显中看到场景以及在场景中跟踪的控制器。
- 如果控制器有支持骨骼输入,就可以看到触摸和按下控制器上按钮的手。
- 将 Interactable 组件添加到场景中的任何对象。 然后,此对象上的所有其他组件将开始从玩家手中接收相关消息。(查看 Samples/Scripts/InteractableExample.cs 示例用法)
- 我们已经包含了一些常用的可交互类,例如 Throwable。 将此组件添加到您的对象将允许它被玩家捡起并抛出。
- 然后,可以将 Skeleton Poser 组件添加到具有 Interactable 的 GameObject,并在与它交互时摆出您想要的手的外观。
- 要将传送添加到场景中,将传送预制件从传送/预制件拖到场景中。 这将设置所有传送逻辑。
- 从 Teleport/Prefabs 中拖入一些 TeleportPoint 预制件以添加玩家可以传送到的位置。
- 您还可以将 TeleportArea 组件添加到场景中的任何对象。 这将允许玩家沿着该对象的碰撞器传送到任何地方。
有了这些基本的构建块,就可以继续创建一些相当复杂的对象。 至于示例,可以查看 SteamVR/InteractionSystem/Samples/Scenes 中的 Interactions_Example 场景。
5.2 Sample scene(示例场景)
Samples/Scenes 文件夹中的示例场景 Interactions_Example 包括所有主要组件,是您熟悉系统的好地方。 该场景包含以下元素:
- Player 玩家:玩家预制体是整个系统的核心。其他大部分组件都取决于玩家是否出现在场景中。
- Teleporting 传送:传送预制体处理系统的所有传送逻辑。
- InteractableExample 交互示例:这显示了一个非常简单的交互,展示了从手接收消息并对其做出反应的基本方面。
- Throwables 投掷物:这些展示了如何使用交互系统来创建各种不同类型的可抛出对象。 阅读每个表格旁边的说明以获取更多信息。
- Skeleton 骨骼:有几个不同的手部模型示例,以及关于骨骼的程度的选项。
- Proximity Button 接近按钮:一个常见的任务是需要按下按钮。物理按钮比平面界面更令人满意,但物理交互系统可能很快变得复杂起来。我们没有深入探讨这个问题,而是包含了一个只要靠近控制器就可以按下的按钮。
- Interesting Interactables 有趣的交互:这些是使用 Skeleton Poser 系统和 Throwables 的稍微复杂的例子。 使用手榴弹,您将获得两种不同的姿势,具体取决于您如何拿起它们。 Happy Ball 在您的手中移动并挤压。
- UI & Hints UI和提示:这显示了如何在交互系统中处理提示,以及如何使用它与按钮等 Unity UI 小部件进行交互。
- LinearDrive 直线驱动:这是一个稍微复杂一些的交互,它结合了一些不同的部分来创建一个可以由简单交互控制的动画对象。
- CircularDrive 环形驱动:这展示了如何对交互进行约束并以不同的方式映射,从而导致更复杂的运动。
- Longbow 长弓:这是实验室中实际使用的长弓。 它现在已更新为输入系统和骨骼姿态。这是我们使用这一系统创造的较为复杂的对象之一,并展示了如何将简单的部件组合成一个完整的游戏机制。在这个示例场景中查看不同的对象可以让你更好地了解交互系统的广度,以及如何将其不同部分结合起来创造复杂的游戏对象。
5.3 Documentation(文件)
现在我们将更深入地了解交互系统中包含的一些基本组件。 该系统分为几个不同的部分:
5.3.1 Core
交互系统的核心是 Player、Hand 和 Interactable 类。 提供的 Player 预制件为场景设置了 Player 对象和 SteamVR 相机。
- 交互系统通过向手交互的任何对象发送消息来工作。 然后,这些对象会对消息做出反应,并且可以根据需要将自己附着在手上。
- 要使任何对象从手接收消息,只需将 Interactable 组件添加到该对象即可。 当手进行悬停检查时,将考虑该对象。
- 我们还包含了一些常用的交互工具,例如 Throwable 或 LinearDrive。
- Player 预制件还创建了一个 InputModule,它允许手模仿鼠标事件以轻松使用 Unity UI 小部件。
- 交互系统还包括后退模式,允许使用键盘和鼠标进行典型的第一人称摄像机控制。 这也允许鼠标可以像玩家的一只手一样操作。 当并非团队中的每个人都可以使用 VR 头盔时,此模式特别有用。(2D Debug:点击后可以通过鼠标和键盘操作 Player 移动)
5.3.2 Player
Player 类就像一个单例对象,这意味着场景中应该只有一个 Player 对象。
- 除了跟踪手和 hmd(Head mounted display,头戴式显示器) 之外,Player 本身不会做太多事情。
- 它可以在整个项目中进行全局访问,交互系统的许多方面都假设 Player 对象始终存在于场景中。
- 它还可以跟踪您是处于 VR 模式还是 2D 后退模式。
- 通过 Player 类使用访问器允许其他组件在不知道是否使用 VR 头盔或鼠标/键盘的情况下同样运行。
- 2D 回退模式很有用,但也有其局限性。 我们主要使用这种模式来测试只需要一只手和触发按钮的非常简单的交互。 它主要在开发过程中很有用,因为并不是团队中的每个人都始终随身携带控制器上的 VR 头盔。
- Player 还包括一些有用的属性:
- hmdTransform:这将始终返回当前相机的 Transform。 这可能是 VR 头盔或 2D 后置相机。
- feetPositionGuess:这会根据 hmd 的位置猜测玩家脚的位置。 由于我们实际上并不知道他们脚的位置,因此取决于玩家的站立方式,这可能非常不准确。
- bodyDirectionGuess:这与 feetPositionGuess 相似,因为它可能不准确
- 注意:Player 类设置为使用图标在编辑器场景视图中显示脚和手,但由于 Unity 的工作方式,这些图标必须位于特定文件夹中才能工作。 这些图标在核心/图标下提供。 将它们移动到项目资源树根目录中名为 “Gizmos” 的文件夹中,它们应该可以工作了。
- 2D 回退模式在测试过程中很有用,但您可能不想在完成的游戏中提供这种模式。 有两种方法可以禁用它:
- 在进行构建之前,取消选中场景中玩家对象上的 “Allow Toggle To 2D” 布尔值。
- 将 “HIDE_DEBUG_UI” 添加到项目 PlayerSettings 中的脚本定义符号列表中。 这只会禁用游戏构建中的 2D 调试视图,同时允许您在编辑器中继续使用它。
5.3.3 Hand
- Hand 类为交互系统承担了大部分繁重的工作。
- Hand 检查其悬停的对象(可交互对象)并根据当前悬停状态向它们发送消息。
- 手一次只能在一个物体上悬停,同时只能有一只手在一个物体上悬停。
- 对象可以附着在手上,也可以从手上分离出来。 手的焦点只能是一个物体,但可以同时有多个物体附着在手上。
- 一旦一个物体与手分离,那么之前附着在手上的物体(如果它仍然附着)成为手上聚焦的物体
- 当手上没有任何东西时,它将始终显示控制器。
- 附着的对象可以设置 AttachmentFlags 来确定手和被附着的对象(被抓取的物体)的行为。
- 可以根据情况锁定手,以免悬停在其他物体或任何物体上。
- 这些是手发送给正在与之交互的对象的消息(messages):
- OnHandHoverBegin:当手刚开始悬停在对象上时发送
- HandHoverUpdate:发送手悬停在对象上的每一帧
- OnHandHoverEnd:当手停止悬停在对象上时发送
- OnAttachedToHand:当对象附着到手时发送
- HandAttachedUpdate:当对象附着在手上时每帧发送一次
- OnDetachedFromHand:当对象从手上分离时发送
- OnHandFocusLost:当附着对象失去焦点时发送,因为其他东西已附加到手上
- OnHandFocusAcquired:当附着对象获得焦点时发送,因为前一个焦点对象已与手分离
在添加 Interactable 脚本的对象上添加下面的脚本,通过手柄的交互获取手柄与物体交互时的 SendMessage。这里仅对部分进行演示:
代码语言:javascript复制using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Valve.VR.InteractionSystem;
public class HandEvent : MonoBehaviour
{
private void OnHandHoverBegin(Hand hand)
{
Debug.Log("当手刚开始悬停在对象上时发送-->" hand.name);
}
private void HandHoverUpdate(Hand hand)
{
Debug.Log("发送手悬停在对象上的每一帧-->" hand.name);
}
private void OnHandHoverEnd(Hand hand)
{
Debug.Log("当手停止悬停在对象上时发送-->" hand.name);
}
}
- 这些是手发送给其子对象的消息:
- OnHandInitialized:当手第一次通过将自身与 SteamVR 跟踪控制器的设备 ID 相关联进行初始化时发送
- OnParentHandHoverBegin:当手开始悬停在某物上时发送
- OnParentHandHoverEnd:当手停止悬停在某物上时发送
- OnParentHandInputFocusAcquired:当游戏窗口获得输入焦点时发送
- OnParentHandInputFocusLost:当游戏窗口失去输入焦点时发送
- 这些成员处理附加和分离:
- AttachObject:使用传入的 AttachmentFlags 从手上附加对象
- DetachObject:从手上分离对象并可选择将其恢复到其原始父对象
- currentAttachedObject:返回手上的焦点附加对象,如果有的话
- Hand 还具有一些有用的属性和功能,可用于自定义其行为:
- OtherHand:这是玩家的另一只手。 这对于需要与双手交互的物体(例如长弓)很有用。
- HoverSphereTransform 和 Radius:这可用于自定义手的悬停范围。
- HoverLayerMask:可以更改此设置,以便手仅悬停在某些图层中的对象上。
- HoverUpdateInterval:根据您的游戏要求,可以或多或少地进行悬停检查。
- HoverLock/Unlock:这用于使手仅悬停在某个对象上。 传入 null 将使手在悬停锁定时不会悬停在任何东西上。 此技术用于在传送弧处于活动状态时使手不会悬停在物体上。
- GetGrabStarting/GetGrabEnding:这些用于确定当时是否正在触发布尔抓取操作。 有两种类型的抓斗 – 抓握和捏抓抓。 这些通常与手柄按钮和触发按钮相关联,但在 Knuckles 控制器上具有特殊功能。
- GetAttachmentTransform:对象可以使用手上的“附件变换”来确定如何捕捉到手。 这些只是 Hand 对象的命名子对象。 Player 预制件包含 “Attach_ControllerTip” 作为示例。
5.3.4 Interactable
- Interactable 类更像是一个标识符。 它向手标识此对象是可交互的。
- 任何带有此组件的对象都会收到来自 Hand 的相关消息。
总结:可以给场景中的物体添加 Interactable 脚本标明物体是可以交互的。添加脚本后,当手接近物体时,物体边缘黄色高亮,提示物体能够进行交互。
5.3.5 Throwable
- 这是最基本的交互对象之一。
- 当一只手悬停在该物体上并按下其中一个抓取按钮(通常是扳机或抓握)时,玩家可以捡起该物体。
- 物体附着在手上并在按下按钮时保持在那里。
- 当按钮被释放时,手中的任何速度都会被赋予抛出的物体。
- 这使您可以创建可以拾取和投掷的基本对象。
注意:Throwable 脚本需要配合刚体组件一起使用。当物体身上没有挂载刚体组件时,添加 Throwable 脚本时会自动帮物体挂载刚体组件 补充:Throwable 脚本一般与 Interactable 脚本一起使用,用来创建可交互的游戏物体
在示例场景中,我们可以通过 Throwing 处的示例了解 Throwable 脚本的使用:
其中,物体投掷时的速度估算模式可以在 Inspector 面板进行设置:
释放速度类型 | 详细 |
---|---|
Get From Hand | 从手部获取速度 |
Short Estimation | 在释放时,将基于前三帧估计速度 |
Advanced Estimation | 在释放时,将找到你投掷的峰值速度,并根据周围的三个帧估计速度 |
在 Throwable 脚本中,我们还可以设置物体抓取时是否穿过物体。通过设置我们可以在抓取物体时使得手以及物体无法穿透场景中的其他物体。
可以穿透 | 无法穿透 |
---|---|
我们可以在 Inspector 面板利用 AttachmentFlags 参数进行设置,相关参数对应左右如下图所示:
在开发过程中,我们根据需要对 AttachmentFlags 进行部分选择来达到我们要的交互效果。例如,实现按动一下扳机键拾取,再按动一下扳机键放下。
5.3.6 LinearDrive
- 这允许用手在开始位置和结束位置之间移动对象。
- 对象的当前位置用于设置一个 LinearMapping。
5.3.7 CircularDrive
- 这允许手以圆周运动的方式移动物体。
- 对象的当前位置用于设置一个 LinearMapping。
5.3.8 LinearMapping
- 这是一个由 LinearDrive 或 CircularDrive 设置的数字。
- 该映射可用于将简单的手部交互映射为更复杂的行为。
- Longbow 中的弦就是一个例子,它使用 LinearMapping 将弓弦的拉动映射到长弓回拉动画。
- 其他几个类使用映射来插入它们的属性
- LinearAnimation
- LinearAnimator
- LinearBlendShape
- LinearDisplacement
- HapticRack
5.3.9 VelocityEstimator
- 此类可用于根据对象位置的变化来估计对象的速度和加速度。
- 在大多数情况下,如果您从实际控制器获得速度和加速度,您将获得更准确的结果,但有时这是不可能的,例如在使用 2D 回退模式下的 “手(鼠标)” 时。
5.3.10 IgnoreHovering
- 如果您希望在执行悬停检查时手将其忽略,则可以将其添加到对象或特定碰撞器。
5.3.11 UIElement
- 将这个组件添加到现有的UI小部件中,手就可以与它进行交互了。
- 这将根据手部交互生成鼠标悬停和单击事件,并通过 Unity 事件系统将它们发送到现有 UI 小部件。
- 此外,它还将生成一个 OnHandClick 事件,该事件也将传递给单击元素的手。
5.3.12 ItemPackage
- ItemPackage 是旨在暂时覆盖手部功能的对象的集合。
- 长弓就是一个例子。 当长弓附在手上时,它接管了手的基本功能。
- ItemPackages 的概念是能够被捡起并放回它们被捡起的地方。
- 一旦被捡起,它们就会一直附着在手上,直到放回原处。 无需按住按钮即可将它们固定在手上。 手仍然像正常一样传递消息,但这些对象通常会禁用手的一些基本功能,例如在它们附着时悬停。
- The Lab 的 ItemPackage 的其他示例是气球工具或 Xortex 无人机控制器。 这两个对象在连接时都会接管手的基本功能。
- ItemPackage 可以是 1 个手或 2 个手。
5.3.13 ItemPackageSpawner
- 这将处理何时生成和收起 ItemPackage 以及如何在生成后将项目附加到手的逻辑。
- 它还处理在拾取时显示项目的预览或项目的轮廓。
5.3.14 ItemPackageReference
- 可以将此组件添加到项目中,以表明它是项目包的一部分。
5.3.15 PlaySound
- 此类允许使用更多参数播放 AudioClips。
- 可以接收多个AudioClips,每次随机播放1个。
- 它还可以随机播放剪辑。
5.3.16 SoundPlayOneShot
- 该类专门针对只播放一次且不循环播放或播放时需要暂停的声音。
5.3.17 Util
- 这是一个充满整个交互系统使用的小型实用函数的类。
5.3.18 InteractableHoverEvents
- 此类在接收到来自手的消息时生成 UnityEvents。
5.3.19 InteractableButtonEvents
- 此类将控制器按钮输入转换为 UnityEvents。
5.3.20 ComplexThrowable
- 本类使用物理关节而不是简单的父方法将物体附着在手上。
- 这允许在附加对象后与对象进行更多基于物理的交互。
- 注意:这个类有点实验性质。 由于我们并没有在 The Lab 中真正使用它,因此它可能功能不完整并且可能有问题。
5.3.21 DistanceHaptics
- 根据 2 个变换之间的距离触发触觉脉冲。
5.3.22 Player (Prefab)
- 这是交互系统的单一部分,结合了其所有基本部分。
- 这个预制件以某种方式安排了玩家和手,使它们都可以轻松访问。
- 它还包含 SteamVR 和 2D 回退系统的所有设置
- 交互系统的大多数其他组件取决于玩家。
- 一个场景中应该只有其中 1 个。
5.3.23 BlankController (Prefab)
- 当手没有其他任何东西时,它会被使用。
- 控制器的渲染模型是通过 SteamVR 加载的,所有部件都是连接在一起的。
5.4 Teleport(传送)
- The Lab 的传送系统支持传送到特定传送点或更一般的传送区域。
- 重要的类是 Teleport、TeleportPoint 和 TeleportArea。
- 所有功能都包含在 Teleport/Prefabs 中的 Teleporting 预制件中。 该预制件包括传送系统运行的所有逻辑。
- 将 TeleportPoints 或 TeleportAreas 添加到场景中以添加玩家可以传送到的地点。
5.4.1 Teleport
- 这个类处理传送的大部分逻辑。
- 按下触摸板时,会显示传送指针。 如果释放触摸板时指针指向有效位置,则玩家会传送。
- 可以在 2D 回退模式下按键盘上的 “T” 来调出传送指针。
- 当玩家传送时,游戏会淡入淡出状态。
- 此类跟踪场景中的所有传送标记,并根据传送指针的状态通知它们淡入/淡出。
- 在某些情况下,对于地面场景使用一个不同于传送网格的单独网格是很有用的。 在这些情况下,传送系统将从它击中传送网格的位置开始追踪,并尝试将玩家放置在地板网格上。 这样做的目的是尝试将场景中的视觉地板与玩家游戏区域中的物理地板匹配起来。
- 有一些属性可能需要调整:
- tracerLayerMask:这是传送指针将尝试击中的所有层
- floorFixupMask:地板所在的层。
- floorFixupMaximumTraceDistance:查找地板的最大跟踪距离。
- ShowPlayAreaMarker:切换是否在传送时显示玩家游戏区域的矩形。 这可以帮助在他们的物理空间中定位玩家。
- arcDistance:传送弧应该走多远。 增加这个数字将允许玩家在场景中传送得更远。 这个值可能需要针对每个场景进行调整。
5.4.2 TeleportMarkerBase
- 这是所有传送标记的基类。
- 它包含 Teleport 类希望出现在所有传送标记中的方法。
- 你可以使用它作为你的基类来创建一种新型的传送标记。
- 传送标记可以被锁定或解锁。 玩家无法传送到锁定的标记。
5.4.3 TeleportArea
- 这是一个由网格组成的传送区域。
- 当传送到这些时,玩家将准确传送到他们指向的位置(加上地板固定)
- 将此组件添加到具有碰撞器和网格渲染器的任何对象,以允许玩家在其上传送。
[注]:需要事先将 Teleporting 预制体拖拽至场景中!否则即使添加脚本也无法实现传送功能。针对 TeleportPoint 也是类似的,也需要事先将该预制体拖拽至场景中。
5.4.4 TeleportPoint
- 这是玩家可以传送到的传送点。
- 当传送到这些上时,玩家将传送到该点的原点,而不管他们指向的点。
- 这些点可以命名。
- 这些点还具有将玩家传送到新场景的能力。 (这不是功能齐全的,因为您必须将其连接到场景加载系统。)
5.4.5 TeleportArc
- 这会为传送指针绘制弧线并为传送系统进行物理跟踪。
5.4.6 AllowTeleportWhileAttachedToHand
- 默认情况下,您无法使用附有物品的手进行传送。 将此组件添加到附加对象会绕过该规则。
- 这由 BlankController 和 longbow Arrow 对象使用,以便玩家即使在它们附着在手上时也可以传送。
5.4.7 IgnoreTeleportTrace
- 将此添加到具有碰撞器的对象将允许传送轨迹穿过它。
- 处理此问题的另一种方法是将该对象放在 TeleportArc 不检查的不同层上。
- 这用于长弓箭以允许传送轨迹穿过箭尖。
5.4.8 Teleporting (Prefab)
- 这个预制件设置了整个传送系统。
- 将它拖到您的场景中将使您能够在游戏中调出传送指针。
- 传送系统的所有视觉和声音都可以通过修改这个预制件的属性来改变。
5.4.9 TeleportPoint (Prefab)
- 将这些添加到您的场景中以添加玩家可以传送到的位置。
- 注意:此场景中的某些对象的名称是硬编码的,如果要更改模型,则需要修改某些代码。
5.5 Render Model(渲染模型)
与SteamVR_Render_Model组件不同,交互系统中的这个Render_Model组件处理控制器模型和手部模型,并单独启用/禁用它们。
5.5.1 Hints
- 提示系统在控制器上显示提示。
- 提示的设置方式可以单独调用控制器上的每个按钮。
- 还可以显示与每个按钮相关的文本提示。
5.5.2 ControllerButtonHints
- 提示是根据控制器的渲染模型设置的。
- SteamVR 提供了从渲染模型组件到按钮 ID 的映射。 此映射用于确定控制器的哪个部分对应于哪个按钮。
- 激活按钮提示后,该按钮将在控制器模型上持续闪烁,直到提示关闭。
- 提示可以仅用于按钮,也可以带有与按钮关联的可选文本提示。
- 有一些静态方法用于与提示系统交互:
- ShowButtonHint:使指定手上的指定按钮闪烁。
- HideButtonHint:停止闪烁指定手上的指定按钮。
- HideAllButtonHints:停止闪烁指定手上的所有按钮。
- IsButtonHintActive:检查指定的按钮是否在指定的手上闪烁。
- ShowTextHint:显示带有与指定手上的指定按钮相关联的传入字符串的文本提示。
- HideTextHint:隐藏指定按钮上指定手的文本提示。
- HideAllTextHints:隐藏指定手牌上当前活动的所有文本提示。
- GetActiveHintText:获取指定按钮的活动提示文本。
5.5.3 Longbow
- Longbow 是使用交互系统创建的复杂游戏机制的一个例子。
- 此处包含的版本与我们在 The Lab 中提供的版本完全相同,包括所有模型、材料和声音。
- Longbow 是使用 ItemPackage 系统构建的。 它由 LongbowItemPackage 预制件组成,该预制件在主手生成 Longbow 预制件,在另一手生成 ArrowHand 预制件。
- 每次发射箭头时,ArrowHand 预制件都会在手中生成一个新的箭头。
- 所有弓箭逻辑都存在于以下脚本中:
5.5.3.1 Longbow.cs
- 它处理弓在无锁定和无锁定模式下如何控制的逻辑
- 它还跟踪拉弓弦的距离
5.5.3.2 ArrowHand.cs
- 根据箭头的位置和控制器按钮处理箭矢和发射箭矢
- 处理在需要时在手中产生箭头
5.5.3.3 Arrow.cs
- 被发射的实际箭头
- 该脚本处理箭头的所有飞行逻辑,包括碰撞检测和决定何时坚持目标
5.5.3.4 ArrowheadRotation.cs
- 每次产生新箭头时随机旋转箭头
5.5.3.5 SoundBowClick
- 播放拉弓弦的声音。
- Longbow 文件夹中的其他脚本处理长弓目标的逻辑
5.5.3.6 ArcheryTarget.cs
- 这是通用射箭目标的脚本。
- 它在被箭头击中时调用 UnityEvent。
5.5.3.7 FireSource.cs
- 表示可以点燃的对象。 一旦着火,这个物体就会在与另一个 FireSource 接触时传播火势。
5.5.3.8 ExplosionWobble.cs
- 用于使射箭目标(箭靶)摆动。
5.5.3.9 Balloon.cs
5.5.3.10 BalloonColliders.cs
5.5.3.11 BalloonHapticBump.cs
5.5.3.12 BalloonSpawner.cs
- 这些脚本处理当 weeble 被箭头击中时产生的气球的逻辑。
5.6 Samples(示例)
- 有一些类是专门为在示例场景中显示一些示例而创建的。
5.6.1 ControllerHintsExample
- 这个类展示了如何使用提示系统。
5.6.2 InteractableExample
- 这个类展示了一个非常简单的接收和响应来自手的消息的例子。
6 Skeleton Poser(骨骼姿态)
Skeleton Poser 系统有一个简单的目的:当拿起物理对象时,你在游戏中的手应该变形为拿着对象的姿势。 这些稳固的姿势可以直接在 Unity 编辑器中创作和调整,以便随着游戏的进行快速迭代。 您可以在姿势之上应用奇特的效果,例如附加的每指动画和动态抓握,以及多姿势混合。
该系统的价值来自于简化的工作流程。 姿势不是处理导入的动画和噩梦般的动画图,而是存储为紧凑的资源,动画会根据与您所持物体相关联的姿势自动应用。 这允许在较小的时间预算内进行更复杂的手部行为。
这些是这些工具的基本功能。它们优于 Unity 动画的地方在于,姿势是在场景视图中创建的,复杂的行为可以通过轻按几个开关堆叠起来。
要将手部姿势添加到游戏中的任何对象,只需向其中添加SteamVR_Skeleton_Poser
脚本即可。 Poser 脚本有两个部分,我们将在下面的内容中介绍这两部分。
6.1 The Basics(基本需求)
SteamVR_Skeleton_Poser脚本旨在独立于SteamVR交互系统运行,并可添加到您自己的系统中,但 SteamVR 交互系统开箱即用,是快速试用的好方法。
SteamVR_Skeleton_Poses是包含特定手部姿势和一些每指动画信息的ScriptableObject。
可以通过SteamVR_Skeleton_Poser脚本及其方便的用户界面添加和修改多个姿势。 您可以为一个 Poser 添加任意数量的姿势,但您可能最多只需要几个。 使用姿势编辑器中的按钮,可以创建新姿势,可以在姿势之间复制姿势数据,可以镜像姿势数据,可以将姿势重置为各种基础,并且可以将场景视图中的骨架更改保存为 改变姿势。 您还可以通过手指移动下拉菜单添加每个手指的附加动画。 这让手指可以根据骨架输入移动,同时保持姿势的约束。 有几种类型的手指运动:
- Static:没有手指移动。 只使用姿势。
- Free:手指自由移动。 忽略姿势。
- Extend:手指可以抬起到完全伸展的位置,但不能比姿势的位置弯曲得更远
- Contract:手指可以卷曲到完全收缩的位置,但不能张开超过姿势所在的位置。
使用 Poser 的混合编辑器选项卡,您可以设置混合行为,以复杂的方式混合和堆叠多个姿势。 将混合编辑器视为动画控制器,将姿势视为动画。 您可以添加三种类型的混合行为:手动、模拟操作或布尔操作。 手动行为必须由代码驱动,只需简单调用:
代码语言:javascript复制Poser.SetBlendingBehaviourValue(string behaviourName, float value)
另一方面,模拟和布尔动作行为由选定的动作自动驱动。 平滑值将是应用于它们的平滑速度,0 表示无。 模拟动作不需要平滑,但推荐用于布尔驱动的行为,因为它们看起来会更平滑。
6.2 Using the Skeleton Poser with the SteamVR Interaction system(将 Skeleton Poser 与 SteamVR 交互系统结合使用)
Poser 组件将自动与 SteamVR 交互系统一起工作。 您需要做的就是将 SteamVR_Skeleton_Poser 脚本添加到可交互的游戏对象中。 交互上有几个设置,您应该确保更改:
- 禁用
Interactable.HideHandOnAttach
。 如果你留下它,这会隐藏你美丽的姿势! - 启用
Interactable.HideControllerOnAttach
。 这将确保您的控制器不会妨碍您的手部姿势。 - 如果您正在创建一个希望能够拿起的可交互对象,请向其中添加
Throwable
脚本。 - 如果您希望投掷物不穿过环境,只需设置以下附件标志:
SnapOnAttach、DetachFromOtherHand、VelocityMovement、TurnOffGravity
。 这就是得到一个简单的可交互的 poser 支持所需要的全部。
如前所述,SteamVR_Skeleton_Poser 脚本旨在独立于 SteamVR 交互系统运行。 如果您使用 SteamVR_Behaviour_Skeleton
脚本来为您的手设置动画,您可以通过调用 BlendToPoser()
告诉它混合到特定姿势器的输出。
如果您使用不同的解决方案来为您的骨骼设置动画,Poser 可以按照 SteamVR_Skeleton_PoseSnapshot
数据类的格式根据命令生成姿势,该数据类保存所有骨骼的对象偏移和位置/旋转。 调用 poser.GetBlendedPose
,传递 SteamVR_Behaviour_Skeleton
或SteamVR_Action_Skeleton
和 SteamVR_Input_Sources
手部标识符。 这将根据该特定姿势的各种行为和选项为您提供完全合成的姿势,您可以自由地将其应用于您的骨骼。
6.3 Pose Editor(姿态编辑器)
姿势编辑器用于创建和编辑姿势(Steamvr_Skeleton_Pose
),可以将其作为脚本对象保存到您的项目中,并用于该对象或游戏中的任何其他对象。
当您第一次将脚本添加到游戏对象上时,在 Inspector 面板会看到一个选项,可以从项目中选择一个姿势,或者创建一个新姿势。
点击创建(Create)后,Unity 会在 Cube 下生成相应的手部模型的克隆体(Clone):
要预览您正在创作的姿势,请单击 “左手” 和 “右手” 部分中的手形图标以在场景中打开和关闭预览。 这些预览骨骼在它们的变换中保存了您的所有修改,因此请记住不要禁用已经进行修改的 Hand,除非它们已使用 “Save Pose
” 按钮保存。
执行此操作时在场景中实例化的手是临时的,只要脚本正确跟踪它们,就会在游戏运行时销毁它们。 在应用于预制件之前禁用双手预览是一种很好的做法,因为预制件中的骨架是凌乱、大且不必要的。
当只启用一个姿势时,最容易编辑姿势,但要使此选项卡中的某些按钮起作用,您需要启用两只预览手。 如果按钮变灰,您可能需要启用一个或两个骨架来激活它。
如果您想修改骨骼的姿势,只需打开可交互对象下方的层次结构。 你可以看到已经添加了一个 vr 手套骨架,你可以进去编辑这些骨骼的变换来形成你的姿势。
点击选择手部骨骼的各个节点,旋转节点可以调整手部姿态。
如果你想做出不对称的姿势,比如说一个不对称的物体——你可以为右手和左手创作一个不同的姿势。 但是,对于简单或对称的对象,您可能希望双手具有相同的姿势,因此您可以使用 Copy x Pose to y hand 按钮将您所做的任何单手修改复制到另一只手上。 当姿势被复制时,手会自动镜像到你的对象上,并且通常会给出完美的结果。 小心此操作,因为它会永久覆盖另一只手的姿势。
修改完成后,点选 Show Left Preview,查看左右手的预览。
预览完成后,点击 Copy Right Pose To Left Hand,使得双手姿态一致。点击 Save Pose 保存修改。
记得将 Interactable 脚本下的 HIde Hand On Attach 取消勾选,勾选了则代表手抓握物体时隐藏手,如果不取消勾选,运行时看不到手部模型。我们可以根据不同物体定制其握持动作。
要向对象添加更多可用姿势,或创建新姿势,请点击顶部姿势列表旁边的小加号按钮。 您将看到创建了一个新选项卡,默认情况下未选择任何姿势,您可以再次从项目中选择一个姿势或创建一个新姿势。 添加 SteamVR_Skeleton_Poser 的姿势将成为稍后可用于混合的姿势。 除了标记为 (MAIN) 的第一个姿势之外,这些顺序无关紧要,被标记为(MAIN)的姿势将是基本姿势。
在每个手形图标下方,您可能已经注意到手指移动的所有选项。 这是用于附加动画,您希望骨骼系统的单个手指动画应用到您创建的姿势之上。 默认情况下,这将设置为静态,但还有其他三个选项。
- Static 静态:无附加动画 。
- Free 自由:如果你不希望你的姿势适用于手指,在这种情况下,它只会听从骨骼系统。
- Extend 伸展:如果手中的姿势是手指的最紧握姿势,则在玩家抬起手指时,手指就会抬起。 这可能是最常见的,因为姿势主要是围绕物体。
- Contract 收缩:与伸展相反,手指处于任何姿势都是手指的最大伸展值,并且只允许进一步向拳头姿势收缩。
6.4 Blending Editor(混合编辑器)
混合编辑器用于创建更加复杂的行为,即在多个姿势之间混合。
点击底部的加号按钮来添加一个新的混合行为,默认情况下称为 new Behaviour。 您可以启用和禁用行为,它们有一个 Influence 滑块,如果您不想在运行时严格启用和禁用它们,您可以在其中关闭和打开它们并使用更多渐变(中间值)。
他们有一个目标姿势,默认情况下,他们将混合到主要姿势。 因为主要姿势是基础,所以这不会做任何事情。 相反,您需要将其设置为已添加到姿势编辑器列表中的次要姿势之一。
共有三种不同类型的混合行为:
Manual:如果您希望此混合由脚本控制或仅在此处使用此值滑块在 Inspector 中设置,您将使用什么。 | Analog:允许您将此混合行为权重映射到项目中的模拟操作之一。 平滑速度可让您对此进行一些平滑处理。 0 意味着没有平滑,任何高于零的都将是缓慢的,随着值的增加,平滑变得越来越快。 一个合适的值应该在 10 到 30 之间,尽管您可能根本不想要任何平滑,因为这是一个模拟动作。 | Boolean:这与模拟动作非常相似,不同之处在于它可以映射到项目中的布尔动作,例如按下按钮。 在这种行为类型中,平滑可能更重要一点,因为如果您没有任何平滑,它将立即跳转。 同样,建议使用 10 到 30 之间的值。 |
如果将混合行为的类型选择为后两种,我们可以为混合行为设置 Action。Analog Action类型对应 Action_single,Boolean Action类型对应 Action_bool。
我们可以添加多个行为,从而在 Blending Behaviour 设置实现不同 Action 绑定不同的手势。但需要注意的是,混合行为需要我们为物体设置多个 Pose。这里我们以示例场景中的 Squishy 物体为例,演示如何设置并绑定。
如上图所示,Squishy 有两个 Pose,如下所示:
其中示例场景中的 Blending Editor 中已经为副姿势设置了 Action 对应于我们手柄的扳机键,这里我们对另一个 Pose 添加 Pose。我们指定动作(Action)为 Grip,在手柄中我们设置了 Grip 动作对应于手柄的侧边键。
平滑速度对应于 Pose 切换的平滑程度,0 意味着没有平滑,瞬间切换。
(写完这部分才发现好像不这样设置也能实现这个效果,直接在示例场景中直接扳机键或者侧边键就行 o_0,不过操作没问题)
每个混合行为的最后一个选项是 Mask。 任何使用过 Unity 的人形动画系统的人都会发现这个 UI 非常熟悉,而那些没有使用过的人会发现它是不言自明的。 如果您不使用 Mask,则混合行为将应用于整只手。 如果您选择使用 Mask,那么您可以选择手的不同部分来应用混合。 绿色部分将应用混合行为,而灰色部分则不会。
通过 Mask 我们可以混合多个姿态,从而实现同一动作的部分混合使用,也可以实现不同动作的部分组合使用。我们使用正方体(Cube)为例,首先创建一个手部姿势(PoseA),之后我们复制 PoseA,对 PoseA 的食指进行编辑,得到 PoseB,两个动作仅仅食指姿势不一致。
我们为两个姿势设置相对应的 Behaviour,同时针对 PoseB 姿势的 Mask 进行设置,勾选 Use Mask 并只保留食指部分的 Pose:
其中 PoseA 对应扳机键,PoseB 对应侧边键,在扣动扳机拿起物体时,可以在按下侧边键可以看到食指动作的变化。
6.5 Manual Behaviours(手动行为)
模拟和布尔行为会自动生成动画,但您必须通过代码手动修改。这是一个示例脚本,它将使用正弦波调制名为 “Example Behaviour” 的行为:
代码语言:javascript复制using UnityEngine;
using System.Collections;
using Valve.VR;
public class PoseModulator : MonoBehaviour
{
SteamVR_Skeleton_Poser poser;
private void Start()
{
poser = GetComponent<SteamVR_Skeleton_Poser>();
}
private void Update()
{
// 设置 blendingBehaviour 的混合值,在 Manual type 的行为中效果最好。
poser.SetBlendingBehaviourValue("Example Behaviour", Mathf.Sin(Time.time * 10) / 2 0.5f);
}
}
结果:
6.6 Scaling(缩放)
出于各种原因,许多游戏都以不同的规模制作。 重要的是您的播放器可能会被放大或缩小。 姿势在运行时以任何 Player 比例应用,这很好,但姿势创作工具默认以正常比例完成。 如果您制作的对象应该在更大的比例下可交互,这将是一个问题,因为您在处理姿势时获得的预览与您在游戏中看到的姿势不匹配。 为了解决这个问题,我们添加了一个属性 Preview Pose Scale,它允许您更改姿势编辑器的工作比例。
此值应设置为您的 Player 的任何比例。
从不同的预览比例保存的姿势将无法区分,它只是编辑器的助手,可以显示您的姿势从不同比例的手应用的样子。
7 文档更新记录
时间 | 操作 |
---|---|
2021-9-2 | 初次整理完成 |
2021-9-3 | 更新了部分内容的排版,补充了快速开始、输入系统的部分内容 |
2021-9-4 | 补充整理了输入系统、骨骼姿态的部分内容 |
2021-9-7 | 补充了 SteamVR 插件安装教程 |
2021-9-15 | 补充了 Interaction System 部分内容 |
2021-9-18 | 补充了 Skeleton Poser 部分内容,添加了示例演示 |
8 小结
文档经过 9 月来断断续续地整理汇总,已基本趋近完整,后续可能不会再这么密集地进行更新。在后续开发过程中,再逐步对其中部分内容进行修改删减,对部分不完善的章节进行完善。中秋将至,预祝中秋快乐 @_@!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/197426.html原文链接:https://javaforall.cn