2024年3月24日发(作者:)

SteamVR Unity插件深度分析

By hendysu

插件中的和已经有一些描述了,这里对里面的每个重要文件进行详

细分析。本文基于SteamVR Unity插件v1.1.0版本。文档最后会更新各最新版本相对于前一

个版本的变化

1. openvr_

位于Plugins//下面。这个是OpenVR SDK的核心,虽然宣称OpenVR开源,也在

github上建了目录,但这个核心的openvr_是不开源的(但它在github上还是开源了

不少东西的,包括valve公司的几个非常有代表性的游戏。参看:

/ValveSoftware)

说一下OpenVR SDK与Unity插件的关系。OpenVR SDK本质上是一套C++的接口,供传

统的用C/C++(比如直接使用OpenGL)来写游戏所使用的。可以看到github上的openvr

目录下,SDK是以二进制的动态库(bin目录及lib目录)+头文件的方式提供的。在samples

目录下有不少示例演示如何调用这个sdk。而Unity插件的核心或者说基础也是OpenVR

SDK,我们可以看到Plugins目录下就是带了openvr_这个SDK,只不过,由于是给

Unity开发者使用的,上面再加了一层C#脚本来封装。我们也可以看到github上供C/C++

开发者使用的openvr_与供Unity开发者使用的openvr_几乎是一样的,仅仅新

增了几个与Unity相关的导出函数:

OpenVR SDK中openvr_中的导出函数

Unity OpenVR插件中openvr_中的导出函数

openvr_的大小不大,只有300多K,显然它也不是VR的核心实现。也是,VR的核

心实现肯定是在SteamVR的运行时当中,OpenVR作为同时支持VIVE和Oculus的SDK,

可以猜测它的工作是对这两者的封装,并对外提供接口。而OpenVR的Unity插件又是通过

C#对OpenVR的封装。

看一下这些导出函数都是干什么的,C#封装中没有注释,但还好C++封装中有注释和例子,

可以参看/headers/openvr.h中的注释。

/** Returns the interface of the specified version. This method must be called after VR_Init. The

* pointer returned is valid until VR_Shutdown is called.

*/

获取指定版本的接口,这个接口应该是与OpenVR交互的核心。需要在调用了VR_init后再

调用。但VR_init并没有导出,在C++版本的SDK中,在头文件中有此函数,是对导出函

数VR_initInternal的封装

VR_INTERFACE void *VR_CALLTYPE VR_GetGenericInterface( const char

*pchInterfaceVersion, EVRInitError *peError );

/** Returns a token that represents whether the VR interface handles need to be reloaded */

返回一个表示VR接口句柄是否需要重新加载的token。根据示例代码,token其实是

VR_InitInternal的返回值(VR_init返回的才是上面的VR_GetGenericInterface返回的VR接

口句柄),如果VR_GetInitToken的返回值与之前保存的VR_InitInternal或者VR_GetInitToken

的返回值不一样了,则表示token有更新,就需要重新调用VR_GetGenericInterface重新获

取了。C++ SDK来看,所有重新操作前都会做这个检查

VR_INTERFACE uint32_t VR_CALLTYPE VR_GetInitToken();

VR_GetStringForHmdError这个函数在C++版SDK中并没有看到导出,在Unity中有,显然

就是获取错误代码的描述字符串