Part 2:如何用Oculus Quest将自己公寓打造成MR科幻游乐场
来源:映维网
在今年8月,映维网分享了Fanbank首席技术官斯科特·盖耶(Scott Geye)是如何用Quest和Unity等工具制作一个炫酷的混合现实公寓。现在,盖耶又通过后续博文介绍了在所述基础上进一步优化混合现实公寓的一系列方式。
延伸阅读 :如何用Oculus Quest将自己公寓打造成MR科幻游乐场
下面是映维网的具体整理:
如何用按钮来为你的公寓实现交互性
在上一篇教程中,我介绍了如何用Oculus Quest和Unity打造一个混合现实公寓的所有步骤。在这个基础之上,我们可以进一步探索强化虚拟公寓的有趣方式。
在我成长的过程中,我喜欢诸如《Cosmic Osmo》和《神秘岛》这样的 游戏 (以及最近的《The Room》)。所述游戏要求你探索一个虚拟世界,并通过与环境交互来发现隐藏的线索。当我在思考如何通过各种有趣功能来进一步装饰我的公寓时,先行隐藏相关控件,并在执行特定操作时显露成为了自然而然的下一步。我想看看自己是否能重现当在房间里发现不存在于现实世界中的元素时的兴奋感觉。
我决定把我的咖啡桌作为主控制中心,但在收到请求之前,我会先把实际的控件隐藏在桌子里面。一旦控件显露,这将提供允许我与整个房间进行交互的方式。我想看看在屋顶开一个大洞会是什么样子,因为这样我就想能够动态地调整公寓内外的环境。我同时想看看摆设一台大电视的感觉。200寸的屏幕可能有点夸张,但超级酷。
在下面这个教程中,我将向你介绍我为房间增加交互性的技术。希望本文能够为你提供启发鼓励,并帮助你天马行空地打造属于自己的科幻未来公寓。
在开始之前,我们需要一定的代码操作,但我编写的脚本可以直接放到你的项目中。当然,如果你希望进一步扩展,我的代码编辑起来应该足够简单。
1. 制作一个隐藏的隔间
在打造和装饰我的数字公寓之后,一个主要的挑战是如何创造一个藏匿控件的地方。我最初并没有设计任何包含隔间或活板门的元素,我所有的家具都来自于预先建造的asset。最简单的方法是使用ProBuilder并在任何需要的地方打一个洞。
ProBuilder有一个实验性的Boolean工具,它允许你将两个ProBuilder对象合并,或从另一个对象中减去一个的体积。根据我的经验,这个工具完全符合我的预期,所以不要被实验这个词吓倒。如果尝试使用更复杂的形状,你肯定会遇到一些小麻烦。所述工具必须从一组三角形中重新创建每个面,所以对于原本可能是每边有两个三角形的立方体,如果你减去圆形,情况就会变得非常复杂,会出现大量的新三角形。这确实有可能导致渲染问题,但这个工具应该不会破坏原始对象,所以你可以尝试一下,看看它的处理效果如何。
你需要在ProBuilder下的Unity Preferences中打开实验功能,然后从ProBuilder/Experimental/Boolean(CSG)Tool下的Tools菜单打开Boolean Tool。
我首先是在咖啡桌上开一个洞并用来放置控制面板。我为桌子使用的预制件被分割成用于桌面和桌腿的对象,但如果你需要,你应该非常容易从零开始创建一个类似的桌子。
要使用Boolean Tool,两个对象都必须是ProBuilder对象,所以你可以使用ProBuilder创建一个新的多维数据集,并使其与原始桌面大小相同,然后关闭原始桌面。接下来,创建一个ProBuilder立方体,将其用作从新桌面(即孔)减去的体积。将它们正确地放在彼此上方,打开Boolean Tool,将新的桌面从对象Hierarchy拖到第一个槽中,然后将减法立方体拖到第二个槽中。将你的Operation选为Subtraction并点击Apply。
这样你就留下三个对象:原始的两个对象和一个新对象,后者是减法运算的结果。这三者在制作动画时非常有用,所以要相应地重命名它们,暂时隐藏两个原始对象,这样你就可以看到减法的效果了。
2. 设置桌子
现在我们的桌子有了一个用于隐藏隔间的洞,而我们同时需要创建隔间的内部、控制面板本身、以及用于显露面板的门。我们将使用Unity的动画工具来确保所有一切协调地移动。
要创建隐藏分区的内部,请找到用于执行布尔减法的立方体。选择顶面,然后稍微插入表面,形成我们隔间的边缘。
接下来,朝立方体底部向下挤出插入面。你应该留下一个看起来像空盒子的元素。把你的立方体放在桌面的洞里,使立方体的顶部略低于桌面。
下一步,创建一个新的立方体来作为我们的控制面板,将其移动到隐藏的隔间内并调整大小。
然后,创建另一个立方体用作可伸缩门。把它移到适当的地方,确保它的大小能盖住这个洞,并且与桌面齐平。确定宽度的测量值,除以这个数的一半,然后以这个宽度设置立方体。接下来,复制立方体,这样你就有了两个门。相应地定位第二个门。
3. 设置控制面板的动画
为了一次过设置所有桌面对象的动画,我们需要将它们全部移动到Hierarchy的同一父对象下面。转到Game Object菜单,选择Create Empty,将其重命名为Control Panel,然后将所有桌面对象拖动到所述对象之下。
为了简单起见,我们将使用Unity的内置动画工具。通过选择Window/Animation/Animation菜单来打开Animation视图。选择我们的Control Panel父对象,然后在Animation视图中单击Create以创建一个新的动画片段,并将其命名为ControlPanelAnim。
在视图中打开新片段后,单击红色录制图标并将时间轴移到1:00(1秒)标记位置。现在,选择每一个伸缩门,将它们缩小到零单位宽,并将它们与孔的最近边对齐。关闭录制并点击播放。门应该从中间打开并显露你的面板。
返回到1:00标记,然后单击Animation视图中的Add Property按钮。打开Panel/Transform并单击Rotation旁边的加号(+)按钮。通过同样的过程来添加Position。然后单击动画控件第二行的Add Keyframe按钮。这将锁定面板的旋转和位置,直到所述时间点,这样它就不会从0:00移动到1:00。接下来,将时间轴移到2:00,单击录制并将面板旋转45度,然后调整其位置,使其面向与房间中面板交互的任何位置。再次关闭录制并点击播放,从而确保你的面板被伸缩门正确显示并旋转到位。
如果运行整个场景,你会注意到动画立即播放。因为我们希望动画被触发,所以我们需要在Animator窗口中进行一定调整。选择ControlPanel对象并打开Animator窗口。你将看到一个连接到ControlPanelAnim状态的Entry状态。右键单击它并创建一个新的Empty状态,然后将其命名为IdleStart。右键单击Entry状态并选择setstatemachine Default State,然后将转换线拖到IdleStart状态。现在,当你开始场景时,动画在被触发之前讲不会播放,因为它永远不会转换到ControlPanelAnim状态。
4. 按钮
我想通过一个简单的按钮机制来触发房间里的所有动画。如果你想深入UI,Mixed Reality Tool Kit(MRTK)是一个很好的资源。但这一次我们将使用Oculus Sample Framework中的预置和脚本。
如果没有试过,我建议你尝试一下Model Train Hand Tracking场景(Assets/Oculus/SampleFramework/Usage/handsinteractiontrainsect)。
这实际上相当有趣。
要在场景中使用相同的按钮,需要添加以下三个预制件:
Assets/Oculus/SampleFramework/Core/HandsInteraction/Prefabs/InteractableToolsSDKDriverAssets/Oculus/SampleFramework/Core/HandsInteraction/Prefabs/HandsManagerAssets/Oculus/SampleFramework/Usage/HandsTrainExample/Prefabs/NearFieldButton.prefab
把NearFieldButton放在场景中的合适地方(我选择了桌子的边缘)。下一步,我们需要配置所有一切以适配场景。
单击HandsManager对象并在Inspector中查看HandManger脚本。返回到Hierarchy,打开OVRCameraRig对象,直到你发现Right和LeftHandAnchors。将每只手对应的OvrHandPrefabs拖到HandsManger Inspector中相应的字段中。
另外,对于每个OvrHandPrefab,你需要确保在Inspector中启用了Enable Physics Capsules。这将在每个食指的尖端添加一个球体,并允许系统捕捉与手指和按钮的交互。
现在我们已经设置了按钮交互,下面我们来构建和运行项目,从而确保手部追踪工作正常。当你触碰按钮时,它应该会亮起,而你会听到一声咔嗒声。
5. 触发动画
现在我们已经完成了按钮和动画,下面我们将两者结合起来。这是我们的第一个脚本。首先,我们需要创建一个空对象来应用脚本。创建一个新的空对象并将其称为PanelController。接下来,为PanelController打开Inspector,单击addcomponent,然后单击NewScript并调用文件PanelController。下面是我们用于触发第一个动画的初始代码:
你应该能够在任何文本编辑器中打开脚本,复制/粘贴上面的内容,保存文件并将其自动导入Unity。如果你再次为Panel Controller对象查看Inspector,你将在Panel Controller(Script)部分看到一个空的Panel字段。将ControlPanel父对象拖动到所述字段,以便我们在脚本中使用它。
我已经将脚本设置成你可以直接在编辑器中运行项目,并通过在Game窗口中点击P键来测试动画。当场景运行时,动画应该会不断循环。要关闭循环,请停止项目,在资源中找到ControlPanelAnim文件,单击文件并查看Inspector,然后取消选中Loop Time。
现在,如果尝试重新运行并按P键,动画将只运行一次。
要将动画链接到按钮,我们需要告诉按钮从脚本调用RunControlPanelAnimation函数。单击NearFieldButton并导航到ButtonController(Script)。单击InteractionableStateChanged列表下的加号(+)按钮,并将PanelController对象拖动到None(object)字段。现在你可以选择PanelController/RunControlPanelAnimation。
现在,你可以在头显中构建并运行项目。单击按钮后你会看到动画开始。
6. 重新隐藏面板
面板打开后,我希望能够再次单击按钮以关闭面板,甚至可以单击动画中间的按钮来再次关闭/打开面板(加分项)。我们不需要创建单独的动画来隐藏面板,我们只需反向运行相同的动画,并使用Animator窗口、Animation States和脚本更新。
我们的计划是将一个动画状态用于打开面板,一个用于关闭面板,一个状态用于动画开始前的待机时间,另一个用于动画结束后的待机时间。这样,我们就可以从脚本中测试动Animaor的状态,并进行适当的转换。
在Animator窗口中,单击ControlPanelAnim状态并将其重命名为AnimForward。复制(复制/粘贴)状态并将其命名为AnimBackward。选择AnimBackward并在Inspector中将Speed值更改为-1,这样动画在所述状态下将向后运行。
选择IdleStart状态,将Speed设置为零,然后将ControlPanelAnim从Assets拖动到空的Motion字段中。复制IdleStart状态并将复制重命名为IdleEnd。添加动画以确保片段的第一帧和最后一帧将在所述状态下播放。
下一步,通过右键单击每个状态并选择Make Transtion来创建三个新的变换:
IdleState to AnimForwardAnimBackward to IdleStateAnimForward to IdleEnd
现在,单击AnimForward to IdleEnd转换,打开Inspector中的Settings并将Transition Offset设置为1。当处于IndleEnd状态时,这将强制动画在最后一帧待机。
所有这一切的结果是,如果AnimForward播放到最后,IdleEnd将开始并停留在最后一帧。如果AnimBackward播放到最后,IdleStart将开始并停留在第一帧。
最后,我们只需要更新脚本来处理这些新状态。
我所做的只是更新我们的processAnimation函数,从而处理我们可能发现的所有四种状态:
IdleState:向前播放动画IdleEnd:向后播放动画AnimForward:我们正在向前播放动画,所以我们需要切换到在动画时间轴的同一位置向后播放动画。AnimBackward:与Animforward相同,但我们是在向后播放,所以我们需要切换到向前播放动画。
我们只能检索每个正在播放的状态的时间。这是一个介于0和1之间的值,它表示我们在动画中的距离,不考虑片段的长度(例如百分比)。当在状态之间切换时,我们需要同时播放反向片段,但要从时间轴的另一端开始播放。这需要我们计算当前播放片段的标准化时间的倒数,并将值作为新的开始位置,然后传递给另一个状态的播放函数。
有了脚本设置,我们可以在动画的任何阶段点击按钮以令它前进或后退,并在开始和结束时暂停。
7. 改变环境
现在我们有了控制面板,我们只需为控制面板添加额外的近场按钮,并在脚本中添加一定的附加功能,然后就可以为我们的房间添加额外的功能。
首先,我们来改变墙壁的颜色。在场景中,将另一个NearFieldButton放置在面板对象的上方,然后使其成为面板的子对象,以便当面板移动时,按钮同样会随之移动。
接下来我们更新脚本以设置墙壁的颜色。
有两个新的公共变量将在PanelController对象的Inspector中显示为空字段。在Wall字段中,选择当前用于墙壁的材质。如果对不想修改的其他对象使用相同的材质,则应复制墙壁材质并仅将其应用于墙壁。第二个字段是一个名为Color1的简单颜色选择器。只需选择你喜欢的颜色即可。
回到脚本,我们有一个名为SetColor的简单函数,它将对墙壁材质应用颜色。点击1并从SetWallColor1函数启动颜色更改。
最后一步是选择新的NearFieldButton,然后再次配置函数调用,方法是单击InteractiveStateChanged列表下的加号(+)按钮,将PanelController对象拖动到显示None(object)的打开字段中,然后选择PanelController/RunSetWallColor1。
我已经将脚本设置成你可以根据需要多次复制/粘贴颜色变量和函数,以便为不同颜色设置多个按钮。你同时可以使用类似的设置来调整skybox。方法是创建skybox材质的公共变量,并在按钮触发所选脚本函数时使用一个简单的函数来设置它们。
当开始添加多个按钮时,你可能需要在面板添加文本标记。我使用了TextMeshPro,它比Unity的内置UI文本要好得多。你只需通过Unity Registry将其安装到Package Manager即可。
最终的房间控制装置
8. 剧院模式和伸缩屋顶
现在所有一切已经准备妥当,你能够触发任何动画或更改场景中任何对象的属性。要制作一个可伸缩屋顶,我最终采用了与控制面板相同的步骤。诀窍是选择代表屋顶的房间对象的面,然后将其分离以创建一个单独的对象,这样我就可以使用Boolean Tool并在其中创建一个大洞。
创建剧院模式涉及一个更为复杂的动画,但就像其他动画一样,我通过设置时间轴和一次记录一个对象的运动来建立动画。我同时降低了房间里所有照明的亮度,使实际的电视屏幕缩放到适合房间的大小。
这里提供了我所有动画和交互的最终脚本。
9. 下一步
我到了一个不得不停下来的时候。对于这个房间,我想做的事情没有尽头。在本教程中,我们确实将自己限制为仅触发动画或属性更新。多亏了Unity动画工具中内置的功能,我们可以走得很远。
对于我的下一个项目,我想尝试类似于在我们混合现实平台中的新应用程序。这需要我们以新的方式使用物理对象。
原文链接:https://yivian.com/news/78527.html
转载须知:转载摘编需注明来源映维网并保留本文链接