一、开发前准备:
二、文档翻译:
开始项目:
- 创建场景:
- 删除
Main Camera
对象
- 将
Player
预设从Core/Prefabs
路径拖入场景。这个预设体设置了主播放器组件和hands 。它还与所有需要的SteamVR相关的东西挂钩。
- 现在可以看到场景,同时控制器(指硬件)在场景中被追踪
- 将
Interactable
组件添加到场景中的任一对象。这个对象上的其他组件将从玩家手柄中接收消息。(可以查看Samples/Scripts/InteractableExample.cs
中的用法)
- 插件中已经包含了一些常用的交互类,比如
Throwable
。将这个组件添加到你想让玩家可以捡起来并可以抛出去的对象上面。
- 如果需要设置传送(个人理解是类似于出门或者进门或者切换场景)逻辑,只需要将
InteractionSystem/Teleport/Prefabs/Teleporting
预设体拖动到场景
8.Teleport/Prefabs
预设体用来添加玩家可以传送到的位置。(每一个对象对应一个传送点)
9.也可以将TeleportArea
组件添加到场景中的任何对象。这样就允许玩家在对撞机上传送该物体(没理解,待验证
)。可以在Samples/Scenes
查看相当复杂的对象
示例场景
1.InteractionSystem/Samples/Scenes/Interactions_Example
包括所有主要组件,是熟悉整个系统的最好场景。场景包含以下元素:
<1> ```Player```预设体是整个系统的核心。大多数其他组件取决于玩家是否出现在场景中。
<2> ```Teleporting```传送预置处理系统的所有传送逻辑。(具体的直接研究代码)
<3> ```InteractableExample```对象显示了一个非常简单的Interactive,它显示了从手接收消息并对其作出反应的基本方面。
<4> ```Throwables```对象展示了如何使用交互系统来创建一个稍微复杂一点的对象,这个对象实际上可以在游戏中使用。
<5> ```UI & Hints```对象显示了如何在交互系统中处理提示,以及如何使用它与Unity UI小部件(如按钮)进行交互。
<6> ```LinearDrive```对象是结合了一些不同的peice来创建一个可以通过简单交互控制的动画对象。
<7> ```CircularDrive```对象展示了如何以不同的方式约束和映射交互,从而导致更复杂的运动。
<8> ```Longbow```(重点)是我们用这个系统创建的更复杂的物体之一,它展示了如何将简单的peice组合起来创建一个完整的游戏机制。
交互系统中的基本组件
1. Core:
<1> 交互系统的核心组件主要有 ```Player``` 、 ```Hand``` 、```Interactable``` ,可以用来设置玩家对象和场景的SteamVR摄像机。
<2> 交互系统的工作原理是将信息发送到手与之交互的任何对象。然后这些物体会对信息做出反应,如果需要的话,它们可以附着在手上。
<3> 要使任何对象接收来自手的消息,只需将可交互组件添加到那个物体。当手执行悬停检查时,将考虑此对象。
<4> 插件中已经包括了一些常用的交互对象,如```Throwable```或```LinearDrive```。
<5> Player prefact还创建了一个InputModule,允许手模拟鼠标事件以轻松的使用Unity UI widgets.
<6> 交互系统还包括一个后备模式,允许典型的第一人称使用键盘和鼠标控制相机。这也允许鼠标像玩家的手。当团队中不是每个人都可以访问虚拟现实时,这种模式特别有用头戴式耳机。
2. Player:
<1> ```Player```是一个```Singleton```。场景中只能有一个玩家
<2> 可以在整个项目中被全局访问,交互系统的许多方面都假设播放器对象始终存在于场景中。
<3> 可以跟踪玩家是处于VR模式还是```2D fallback ```模式
<4> 通过Player类使用访问器可以让其他组件以类似的方式工作,而不必知道是否正在使用虚拟现实耳机或鼠标/键盘。(我个人理解为调试模式,用鼠标键盘模拟)
<5> 2D fallback 模式主要用来测试非常简单的交互,只需要一只手和触发按钮,主要用来调试。
<6> 以下是重要的属性:
* ``` hmdTransforms ``` : 将始终返回当前摄像机组件。包括VR设备和模拟设备的摄像机
* ``` feetPositionGuess ``` : 根据VR设备的位置来猜测玩家脚的位置,因为实际上不知道玩家脚的位置,因为不确定玩家是否是站着
* ```bodyDirectionGuess``` : 身体方向的,和上面的属性相同,取决于玩家的站姿
<7> Player类被设置为在编辑器场景视图中使用图标来显示脚和手,但是由于Unity的工作方式,这些图标必须位于特定的文件夹中才能工作。这些图标在Core/icons下提供。将它们移到项目资源根目录下名为“Gizmos”的文件夹中,它们就可以工作了。
<8> 2d fallback 模式主要用来测试,发布正式版本的时候可以通过以下方式禁用:
* 在编译之前,取消选中 ```Player对象```上的 ```Allow Toggle To 2D```
* 在项目中的 ```PlayerSetting```脚本中添加预编译宏 ```HIDE_DEBUG_UI```,在调试模式下使用 2d fallback 模式,发布之后使用的VR设备模式
3. Hand :
<1> Hand类负责交互系统的大部分重担。
<2> 手会检查其悬停的对象(可交互对象),并根据当前悬停状态向它们发送消息。
<3> 手一次只能在一个对象上悬停,同时只有一只手可以在一个对象上悬停。
<4> 物体可以附着在手上,也可以从手上分离。只有一个对象可以是手的焦点对象,但可以同时将多个对象附加到手上。
<5> 一旦一个对象从手上分离,那么先前附着到手上的对象(如果它仍然附着)将成为手上焦点对象
<6> 当手上没有东西时,它将始终显示控制器。
<7> 附加对象可以设置```AttachmentFlags```,这些标志确定手和对象在附加后的行为。
<8> 根据情况,手可以被锁定,不会悬停在其他物体或任何物体上。
<9> 以下是手和交互对象的消息:
* OnHandHoverBegin:当手开始在对象上悬停时发送
* HandHoverUpdate:发送手悬停在对象上的每一帧
* OnHandHoverEnd:当手停止在对象上悬停时发送
* OnAttachedToHand:当对象附着到手上时发送
* handatchedupdate:当对象附加到手上时发送每帧
* OnDetactedFromHand:当对象与手分离时发送
* OnHandFocusLost:当附加的对象因为其他对象已附加到手而失去焦点时发送
* OnHandFocusAcquired:当一个附加对象获得焦点时发送,因为先前的焦点对象已经从手上分离
<10> 以下是手向其子对象发送的消息
* OnHandInitialized:通过将自身与SteamVR跟踪控制器的设备ID关联来初始化手时发送开始在手上悬停
* OnParentHandHoverEnd:当手停止在某个对象上悬停时发送
* OnParentHandHoverBegin :当手开始在某物上悬停时发送
* OnParentHandInputFocusAcquired:当游戏窗口获得输入焦点时发送
* OnParentHandInputFocusLost:当游戏窗口失去输入焦点时发送
<11> 以下成员负责连接和分离:
* AttachObject :使用传入的AttachmentFlags从手附加对象
* DetachObject :从手部分离对象,并有选择地将其恢复到原来的父节点
* currentAttachedObject :这将返回手上的焦点附着对象(如果有的话)
<12> 其他的功能:
* OtherHand : 这是另一只手在玩家身上。这对于需要与双手交互的对象(如longbow)非常有用。
* HoverSphereTransform and Radius (没有找到全部对应的 ```Radius```的属性,可能是包含):可用于自定义手的悬停范围。
* HoverLayerMask :可以更改此设置,使手只悬停在某些层中的对象上。
* HoverUpdateInterval : 根据游戏的要求,悬停检查可以或多或少地进行。
* HoverLock/Unlock:用于使手只悬停在某个对象上。传递null将使手在悬停锁定时不会悬停在任何对象上。此技术用于使手在传送弧处于活动状态时不悬停在对象上。
* GetStandardInteractionButton/Up/Down:用于检查控制器上触发器的状态。这对于也可以与二维回退手一起使用的简单对象很有用。在2D回退情况下,左键单击充当标准交互按钮,对象的行为相同。
* GuessCurrentHandType:这使用一些SteamVR函数来确定哪只手最左边,哪只手最右边。
* GetAttachmentTransform:对象可以使用手上的“附件变换”来计算如何捕捉到手。这些只是手对象的命名子对象。Player预置包含“Attach_ControllerTip”作为示例。
4. Interactable :
<1> 可交互类更像是一个标识符。它向手标识这个对象是可交互的。
<2> 任何具有此组件的对象都将接收来自手的相关消息。
<3> 仅使用这三个组件,您应该能够创建许多不同的和复杂的交互式对象。
<4> 一些常用的交互系统组件展示了系统如何结合这些基本机制来创建更复杂的对象:
5. Throwable :
<1> 这是最基本的交互对象之一。
<2> 当一只手悬停在这个物体上并按下交互按钮(触发器)时,玩家可以捡起它。
<3> 当按下按钮时,物体会附着在手上并保持在那里。
<4> 当扳机被释放时,手上的任何速度都被赋予投掷的物体。
<5> 这使您可以创建可以拾取和抛出的基本对象。
6. LinearDrive :
<1> 这允许用手在起始位置和结束位置之间移动对象。
<2> 对象的当前位置用于设置LinearMapping。
7. CircularDrive :
<1> 这使得一个物体可以用手做圆周运动。
<2> 对象的当前位置用于设置LinearMapping。
8. LinearMapping :
<1> 这是一个由LinearDrive或CircularDrive设置的数字。
<2> 该映射可用于将简单的手交互映射为更复杂的行为。
* 这方面的一个例子是Longbow中的字符串,它使用线性映射将弓字符串的拉动映射到长弓回拉动画。
<3> 其他几个类使用映射来插值它们的属性
* LinearAnimation
* LinearAnimator
* LinearBlendShape
* LinearDisplacement
* HapticRack
9. VelocityEstimator :
<1> 这个类对于根据物体位置的变化来估计物体的速度和加速度很有用。
<2> 在大多数情况下,如果你从实际控制器获得速度和加速度,你会得到更准确的结果,但有时这是不可能的,例如当使用2D回退手。
10. IgnoreHovering :
<1> 如果希望在执行悬停检查时手忽略它,可以将其添加到对象或特定碰撞器中。
11. UIElement :
<1> 将这个组件添加到一个现有的UI小部件中可以使手与之交互。
<2> 这将生成基于手交互的鼠标悬停和单击事件,并通过Unity事件系统发送它们,以使用现有的UI小部件。
<3> 此外,它还将生成一个OnHandClick事件,该事件也将传递给单击元素的手。
<4> 交互系统的另一个重要部分是ItemPackage的概念
12. ItemPackage :
<1> ItemPackage是用于临时覆盖手部功能的对象的集合。例如长弓。当长弓附在手上时,它有点接管了手的基本功能。
<2> itemspackages的概念是能够被提取并放回原来的位置。
<3> 一旦捡起它们,它们就一直附着在手上,直到它们被放回原处。不需要按住按钮就可以保持与手的连接。手仍然像普通的一样传递消息,但是这些对象通常会禁用手的一些基本功能,例如在附加对象时悬停。
* 来自实验室的项目包的其他例子是气球工具或Xortex无人机控制器。这两个对象在连接时接管手的基本功能。
<4> 物品包可以是单手或双手。
13. ItemPackageSpawner :
<1> 它处理何时生成和放置ItemPackage以及如何附加的逻辑手上的物品一旦产生。
<2> 它还处理显示项目预览或项目提货时的大纲。
14. ItemPackageReference :
<1> 可以将此组件添加到项以指示它是项包的一部分。
<2> 作为交互系统的核心部分,还有一些其他的helper类。
15. PlaySound :
<1> 它可以接收许多音频片段,每次随机播放1个
<2> 它还可以随机播放剪辑的方式
16. SoundPlayOneShot :
<1> 这个类是专门为只播放一次而不循环或需要在播放时暂停的声音
17. Util :
<1> 这是一个充满了在整个交互系统中使用的小实用程序函数的类。
18. InteractiableHoverEvents :
<1> 这个类在从手部接收消息时生成UnityEvents。
19. InteractableButtonEvents :
<1> 此类将控制器按钮输入转换为UnityEvents。
20. ComplexThrowable :
<1> 这个类使用物理关节将对象附加到手上,而不是简单的父子关系。
<2> 这就允许了更多的物理基础上的相互作用,一旦它是附加的。
<3> 注:这节课有点实验性。因为我们并没有在实验室中使用它,所以它可能功能不完整,而且可能有缺陷。
21. DistanceHaptics :
<1> 根据两个变换之间的距离触发触觉脉冲。
22. Player (Prefab) :
<1> 这是交互系统的一部分,它结合了所有的基本部分。
<2> 这个Prefab的安排Palyer和手的方式,使他们都很容易接近。
<3> 它还包含SteamVR和2D fallback系统的所有设置
<4> 交互系统的大多数其他组件都依赖于播放器,其中一些组件假定播放器和手是以这种方式设置的。
<5> 一个场景中应该只有一个。
23. BlankController (Prefab)
<1> 这是Hand在没有其他东西附着的情况下使用的。
<2> 虚拟现实的所有部件都是通过虚拟现实的渲染器连接而成的。
24. 传送功能 :
<1> 实验室的传送系统支持传送到特定的传送点或更一般的传送区域。
<2> 主要的类有```Teleport```,```TeleportPoint```和```TeleportArea```。
<3> 所有的功能都包含在``` Teleport/Prefabs```中的传送预制件中。这个预设包括传送系统的所有逻辑功能。
<4> 在场景中添加```TeleportPoints```或```TeleportAreas```以添加玩家可以传送到的地点。
<5> ```Teleport```类 :
* 这个类处理心灵传送的大部分逻辑。
* 按下触摸板时,传送指针显示。如果释放触摸板时指针指向一个有效点,则玩家将传送。
** 在2D回退模式下,您也可以按键盘上的“T”键来调出传送指针
* 当玩家传送时,会有轻微的暗显到黑色,然后游戏又会淡入。
* 这个类跟踪场景中的所有传送标记,并根据传送指针的状态通知它们淡入/淡出。
* 在某些情况下,为地板设置一个不同于传送网格的场景的单独网格是很有用的。在这些情况下,传送系统会追踪到它击中传送网的地方,并尝试将玩家放在地板上。这样做的目的是尝试将场景中的可视地板与玩家游戏区域中的物理地板相匹配。
* 可能需要调整的属性
** tracerLayerMask:这是传送指针将尝试命中的所有层
** floorFixupMask:地板所在的层。
** floorFixupMaximumTraceDistance:尝试查找地板时要跟踪的最大距离。
** ShowPlayAreaMarker:此选项用于切换是否在传送时显示玩家游戏区域的矩形。这有助于引导玩家在他们的物理空间。
** arcDistance:传送弧应该走多远。增加这个数字将允许玩家在场景中进一步传送。可能需要为每个场景调整此值。
<6> ```TeleportMarkerBase```类 :
* 这是所有传送标记的基类。
* 它包含Teleport类期望在所有Teleport标记中出现的方法。
* 你可以用它作为基类来创建一个新类型的传送标记。
* 传送标记可以锁定或解锁。玩家不能传送到锁定的标记。
<7> ```TeleportArea```类 :
* 这是一个由网格组成的传送区域。
* 当传送到这些,玩家将传送到他们所指的地方(加上地板固定装置)
* 将此组件添加到具有碰撞器和网格渲染器的任何对象中,以允许玩家在其上传送。
<8> ```TeleportPoint``` 类 :
* 这是一个传送点,玩家可以传送到。
* 当传送到这些点上时,玩家将在点的原点传送,而不管他们指向的点在哪里。
* 这些点可以命名为
* 这些点还具有传送玩家到新场景的能力。(这不是完全的功能,因为您必须将其连接到场景加载系统。)
<9> ```TeleportArc``` 类 :
* 这将为传送指针绘制弧线,并对传送系统进行物理跟踪。
<10> ```AllowTeleportWhileAttachedToHand``` 类:
* 默认情况下,你不能用一只手来传送。将此组件添加到附加对象将绕过该规则。
* 这是使用```BlankController```和``` longbow Arrow```对象,以便玩家可以传送,即使他们是附在手上。
<11> ```IgnoreTeleportTrace``` 类:
* 用对撞机将其添加到一个物体上,将允许传送轨迹通过它。
* 处理这个问题的另一种方法是把这个物体放在一个不同的层上,而这个层是```TeleportArc```不会检查的。
* ```arrow tip```用来传送``` longbow Arrow```。
<12> ```Teleporting (Prefab)``` :
* 这个预制体建立了整个传送系统。
* 将此拖动到你的场景将使你能够在游戏中打开传送指针。
* 所有的视觉和声音传送系统可以改变通过修改这个预置的属性。
<13> ```TeleportPoint (Prefab)``` :
* 将这些添加到场景中以添加玩家可以传送到的位置。
* 注意:此场景中某些对象的名称是硬编码的,如果要更改模型,则需要修改部分代码。
25. 提示功能 :
<1> 提示系统在控制器上显示提示。
<2> 提示的设置方式是,控制器上的每个按钮都可以单独调用。
<3> 还可以显示与每个按钮相关联的文本提示。
<4> ```ControllerButtonHints```类 :
* 提示是根据控制器的呈现模型设置的。
* SteamVR提供了从渲染模型组件到按钮id的映射。这个映射是用于计算控制器的哪个部分对应于哪个按钮。
* 一旦某个按钮的提示被激活,该按钮将在控制器模型上持续闪烁,直到提示关闭。
* 提示只能用于按钮,也可以与按钮关联的可选文本提示。
* 有几种静态方法用于与提示系统交互:
** ShowButtonHint:在指定的手上闪烁指定的按钮。
** HideButtonHint:停止在指定的手上闪烁指定的按钮。
** 隐藏按钮提示:停止闪烁指定手上的所有按钮。
** IsButtonMaintactive:检查指定的按钮是否在指定的手上闪烁。
** ShowTextHint:显示一个文本提示,其中传递的字符串与指定手上的指定按钮关联。
** HideTextHint:隐藏指定按钮上指定手的文本提示。
** hidealltextshints:隐藏指定手上当前活动的所有文本提示。
** GetActiveHintText:获取指定按钮的活动提示文本。
26. 指示箭头:
<1> Longbow是使用交互系统创建的复杂游戏机制的一个例子。
<2> 这里包含的版本与我们在实验室里提供的版本完全相同,包括所有的模型、材料和声音。
<3> Longbow是使用```ItemPackage```系统构建的。它由```LongbowItemPackage```预制在主手生成 ``` Longbow prefab```, 另外一只手生成```ArrowHand prefab``` 。
<4> ArrowHand Prefab 是在每次发射一个新的 ```ArrowHand Prefab ```之后在手上产生的新的箭头。
<5> 所有的弓箭逻辑都出现在以下脚本中:
* Longbow
** 它处理弓如何在有凹痕和无凹痕模式下控制的逻辑
** 它还可以记录弓弦被拉多远
* ArrowHand
** 根据箭头的位置和控制器按钮处理开槽和发射箭头
** 处理在需要时在手上生成箭头
* ArrowheadRotation
** 每次生成新箭头时随机旋转箭头
* SoundBowClick
** 播放拉弓弦的声音。
<6> Longbow文件夹中的其他脚本处理Longbow目标的逻辑
* ArcheryTarget
** 这是一个通用射箭目标的脚本
** 当被箭头击中时,它会调用UnityEvent。
* FireSource // TODO
** 表示可以点燃的对象。一旦着火,当它与另一个火源接触时,这个物体就会蔓延开来。
* ExplosionWobble
** 用来使射箭目标摆动。
* Balloon
* BalloonColliders
* BalloonHapticBump
* BalloonSpawner
** 这些脚本处理当weeble被箭头击中时产生的球的逻辑。
27. Samples:
<1> 有几个类是专门为在示例场景中显示一些示例而创建的。;
<2> ```ControllerHintsExample```
* 这个类演示如何使用提示系统。
<3> ```InteractableExample```
* 这个类展示了一个非常简单的例子,它演示了从手部接收和响应消息。