SteamVR(HTC Vive) Unity插件深度分析(七)
7. Prefabs
里面有3个预制体
7.1.[CameraRig]
这是Extras目录下两个示例场景使用的预制体(Scenes下面的示例也用了这个预制体)。它包含了左右两个控制器以及头部相机。可以参看下图的结构(左右控制器结构是一样):
在实际运用过程中,要给现有场景添加vive支持,直接将SteamVR_Camera.cs添加到场景中的主相机上,然后点击相机Inspector中SteamVR_Camera.cs中的Expand按钮(这个过程可以参看SteamVR_Camera.Expand的实现),就会自动生成类似于[CameraRig]中的相机结构,但并不会有里面的Controller。要添加控制器,可以参考这个预制体的做法。如果你的场景中的相机没有特殊的要求,也可以删掉原来的相机,然后直接使用这个预制体。
7.1.1. Camera(eye)
这个是最原始的场景中的相机,它的inspector视图如下:
在原始相机的基础上添加了SteamVR_Camera.cs和SteamVR_CameraFlip.cs两个脚本,这两个脚本的最终作用都是对相机渲染出来的原来图像进行一定的变换(即后期处理)。SteamVR_Camera中的Wireframe配置如果选中,场景中的所有物体都是以网格形式显示的。
7.1.2. Camera(ears)
这个是模拟耳朵的,在一个空物体上添加了Audio Listener和SteamVR_Ears.cs脚本:
其中的Vrcam配置是指向SteamVR_Camera对象,如果没有指定,在代码中也会自动获取的。
7.1.3. Camera(head)
这个是模拟头部,上面最重要的就是头显设备了:
注意,这个上面也有个Camera,它是在PC上显示的那个称之为伴随窗口(Companion Window)的视角(注意它的参数,比如Clear标志为Don’t Clear,而Depth为0,这会使得它可以显示主相机渲染后的图像,因为主相机的Depth为-1。不过这里并不是因为参数设置而让它显示渲染图像的,而是在SteamVR_GameView脚本中直接画到这个相机上的)。然后加了SteamVR_GameView.cs和SteamVR_TrackedObject.cs脚本。SteamVR_TrackedObject是添加到所有的跟踪设备上的,这里代表的就是头显,可以看到SteamVR_TrackedObject中的index选择的是Hmd。
几个配置参数:
Scale(SteamVR_GameView):伴随窗口中物体相对于hmd中的物体的放大倍数,可以在运行时实时修改查看效果
DrawOverlay(SteamVR_GameView):这个表示是否在伴随窗口中显示overlay的内容
Index(SteamVR_TrackedObject):这个表示头显设备的跟踪索引,这里指定了0(即hmd),因为头显的索引是唯一确定的。根据实践,这里必须指定索引,而不会自动设置索引,大概是头显的索引是固定的,不会通知
Origin(SteamVR_TrackedObject):这个可以设置当前跟踪设备所在(或者说所基于)的位置,从底层通知过来的位置数据会叠加到这个位置之上,通常不指定
IsValid(SteamVR_TrackedObject):这个变量没啥用,属于废弃的变量
7.1.4. Contoller(left)/Controller (right)
这个是左右控制器(即手柄),以左手柄为例:
它本身就是一个空物体上加了个SteamVR_TrackedObject脚本,因为手柄也是一个跟踪设备,这里并没有指定索引,因为手柄的索引并不是固定的,而是动态的,是通过SteamVR_ControllerManager来设置的
在Controller下面还有一个Model子对象:
上面有一个SteamVR_RenderModel脚本,是用来渲染控制器模型的,它会自动往Model下面添加手柄的模型。几个配置参数:
Index:同样是跟踪设备(这里为控制器)的索引
ModelOverride:选择一个控制器模型。这个只在编辑模式下有用。它的作用就是用来查看系统自带的那些控制器、头显、基站等模型的。在运行状态下,这个设置是不起作用的
Shader:模型所使用的Shader
Verbose:会打印一些log
CreateComponents:模型支持的话,会创建多个小部件,否则只会创建一个整体的模型
UpdateDynamically:动态更新模型位置,这个只在运行状态下有用
7.1.5. CameraRig(origin)
这个就是预制体的顶层对象了,它上面有SteamVR_ControllerManager和SteamVR_PlayArea脚本:
SteamVR_ControllerManager对控制器进行管理,包括连接、索引等,SteamVR_PlayArea用于在编辑器中显示一个游玩区,而上面还有MeshRender/MeshFilter,它们是用于配合SteamVR_PlayArea显示游玩区用的。其中的一些设置参数:
Left/Right(SteamVR_ControllerManager):分别指向左右两个控制器对象(带SteamVR_TrackedObject)
Objects(SteamVR_ControllerManager):这是一个数组,还可以对其它控制器进行管理
BorderThickness(SteamVR_PlayArea):这个是边界区域的宽度
WireframeHeight(SteamVR_PlayArea):在场景中看到的游玩区长方体的高度
DrawWireframe When Selected Only(SteamVR_PlayArea):是否仅在选中时才显示游玩区方框
DrawIn Game(SteamVR_PlayArea):是否在Game视图中也绘制出游玩区边界(地面的部分)
Size(SteamVR_PlayArea):游玩区的大小,单位厘米
Color(SteamVR_PlayArea):游戏区边界(地区部分)的颜色
7.2.[Status]
里面封装了一些有用的组件,这个是可以加到自己的工程里面的。不过里面包含的东西比较杂,不一定都要,可以参照实现自己的。这个预制体在Scenes/exmple.unity这个场景里面有用到。它由6个组件组成,如下:
7.2.1. Calibration
它里面除了基本的Transform组件外,还有一个取消显示了的GUI Text组件和SteamVR_StatusText.cs这个脚本组件:
用于在Vive进行房间设置时进行相应的提示。提示有渐显和渐隐效果,这个逻辑在SteamVR_StatusText中实现,文字的显示利用了GUIText组件。几个设置参数:
Message:这个是自定义的事件名称。calibrating表示正在测量事件
Duration:这个表示信息文字持续显示的时间。这里为0,其实是不关注这个参数
Fade:这个是文字渐显/渐隐的时间
Mode:表示在指定事件的什么状态下显示。“WhileTrue”表示calibrating事件的过程中持续显示
7.2.2. _Stats
这个是显示统计信息的一个组件(目前仅显示帧率和丢帧数)。它上面还有一个Camera,通过它将GUIText渲染到overlay的纹理上,通过overlay将文字信息显示出来。它显示出来的样式为:
在头显和伴随窗口都有显示。在头显中并不是一直显示在最前面,而是在固定在z方向的一个位置,因此可以从不同角度观察,而在伴随窗口是一直显示在最前面的(因为在伴随窗口中,overlay是直接绘制在场景图像之前的)
这里在测试的时候可能看不到效果,可以从几个方面检查:
1、在[Status]预制体中的Overlay对象中的SteamVR_Overlay有没有勾选
2、需要在Game视图按“i”键来切换显示与隐藏
3、Transform中的position决定了显示的位置(与GUIText中的对齐方式结合)。Z参数是不起作用的是,因为会通过overlay显示
4、GUILayer没有禁用
5、重新选择一下overlay这个纹理(原因未知)
注意相机参数中,Target Texture要选择overlay这个render texture,同时在SteamVR_Overlay中也选择这个纹理。
SteamVR_Stats的几个参数:
Text:显示文字的GUIText组件,可以手动指定,不指定的话,会自动搜索当前物体上的GUIText组件
FadeColor/Fade Duration:统计信息显示出来时的渐显颜色和时间。只在Awake的时候有用,所以基本看不出来效果,没有用的设置
SteamVR_Menu名义上是菜单,实际上是一个二维的配置界面,可以配置一些显示参数,如下图所示:
它有如下几个参数:
Cursor:光标纹理
Background:背景纹理
Logo:上部有一个大Logo
LogoHeight:logo的高度
MenuOffset:相当于Menu显示的margin
ScaleLimits:相机缩放的范围
ScaleRate:可以通过键盘的PageUp/PageDown来进行缩放,这个参数是设置每按一次的缩放倍数的
7.2.3. TrackingLost
这个是失去跟踪后给的文字提示(可以通过把头显藏到基站检测不到的地方测试),因为持续时间比较短,可以加长Duration参数,或者可以将Mode由On True改为While True。
这里面三个组件,Transform用于确定显示位置,GUIText用于显示的文字内容和效果,SteamVR_StatusText用于控制文字的显示。message字段是SteamVR_StatusText的父类SteamVR_Status中的一个变量,定义了要接收的事件(字符串形式表示)。这里“out_of_range”是OpenVR中定义的当玩家离开跟踪区域时的一个事件(并不是OpenVR发出来的,而是一个自定义消息,在Scripts/SteamVR.cs中自定义的一个事件)。
几个参数:
Message:out_of_range,自定义事件,这里是走出游玩区,或者失去基站跟踪时
Duration:文字显示及隐藏的时间
Fade:文字显示或隐藏时渐变的时间
Mode:“On True”表示“out_of_range”事件为true时显示,即处于未跟踪状态时显示
TODO 这里的文字也是通过overlay来显示的,有两个疑问,一个是这里看不到任何与overlay有关的东西(包括SteamVR_StatusText及SteamVR_Status脚本),为什么还跟overlay相关?比如去掉[Status]预制体中Overlay中的SteamVR_Overlay选择,文字就显示不出来了。二是这里与上面的_Stats不同,上面有独立的相机来渲染,这里没有,但也能显示出来。——经过实践发现是,这些GUIText实际上都借用了_Stats下面的Camera和GUILayer,把这两个中的任意一个禁用,SteamVR_StatusText就显示不出来了。这个是Unity的特性吗?在head上也有一个Camera和GUILayer,为什么没有使用它?
7.2.4. TrackingRestored
这个是恢复跟踪时的提示信息。
这个与TrackingLost是类似的,唯一不一样的是Mode为“On False”,即当“out_of_range”事件为false时显示,即从失去跟踪到恢复跟踪的2秒时间内显示
7.2.5. SteamInitFailure
Steam初始化失败的文字提示
它是在“steam_init_failure”事件时显示,显示的时间比较长,为90秒
7.2.6. Overlay
Overlay是SteamVR的一个概念,基本上作用就是一个2D(UI)的界面叠加到场景上面显示出来,有一个专门的IVROverlay接口来操作overlay。
只加了一个SteamVR_Overlay.cs这个脚本组件,看起来很简单,实际上这个脚本还比较复杂。readme.txt中有说SteamVR_Overlay比较耗资源。几个参数:
Texture:这个要选定overlay这个纹理。这个纹理位于本地目录Assets/SteamVR/Texture/overlay.renderTexture
Curved:这个表示overlay以弧形界面的方式显示(有环绕效果)
Antialias:反走样(抗锯齿)
Highquality:所谓的高质量overlay
Scale:名为Scale,实际为overlay的宽度
Distance:Overlay与相机的距离(还需要考虑transform中的z参数)
Alpha:透明度
UVOffset:纹理的uv坐标及缩放倍数
MouseScale:类似于鼠标灵敏度的参数(TODO 待确认)
CurvedRange:曲面的范围,大概可以设置曲率(TODO 待确认)
InputMethod:输入方式(TODO 作用待确认)
7.3.[SteamVR]
这个预制体就是加了SteamVR_Render.cs这个脚本:
所以核心是SteamVR_Render.cs这个脚本,它的作用有两个,一是控制渲染流程,二是事件分发。这个预制体必须要有,如果没有,也会自动创建。几个参数:
PauseGame When Dashboard Is Visible:是否在显示控制面板时暂停游戏(在游戏过程中按系统键就会弹出控制面板),实际做法是将Unity的Time.timeScale设为0,相当于时间暂停了
LockPhysical Update Rate To Render Frequency:锁定物理更新频率为(头显)渲染帧率。这个会根据头显的渲染帧率来计算Unity的更新频率
ExternalCamera:外部相机。它的作用是制作那种将玩家的现实场景与虚拟的游戏场景融合的视频用的。可以看一个这样的视频的例子:
https://www.youtube.com/watch?v=w9dQkiI8raY。
关于External Camera,官方开发者在论坛有一个详细的解释:https://steamcommunity.com/app/358720/discussions/0/405694031549662100/。
这里有介绍如何操作:https://www.htcvive.com/cn/forum/chat.php?mod=viewthread&tid=1170
ExternalCamera Config Path:外部相机配置文件路径。缺省的是在游戏根目录下的externalcamera.cfg
LeftMask/Right Mask:可以为左右眼设置不同的Mask,使左右眼可以看到不同的图像
TrackingSpace:跟踪空间的类型,可以设为坐姿和站姿。坐姿和站姿的区别是视角的高度。