VR大空间资料 03 —— VRGK使用体验和源码分析
自用文档,UE4.27项目 HTC Vive VR和Oculus Quest 2
SteamVR串流运行于HTC Vive VR 和 Oculus Quest 2设备
打包apk运行于Oculus Quest 2设备
VRGK - Virtual Reality Game Kit v3.0 可蹲下 可看自身IK 无局域网
https://www.unrealengine.com/marketplace/zh-CN/product/vrgk-virtual-reality-game-kit
UE 4.27 -> VRGK v3.0
UE 4.25, 4.26 -> VRGK v2.1
API文档在《虚幻商城 VR IK》
VRGK 基于OculusVR , 不需要Nav自动寻路组件
Dust and Smoke Effects 4.25-4.26
WaterVFXNiagara
http://cheapcg.com/
https://github.com/davidbuenov/VRGK-Community-Project-UE5
[虚幻引擎5 VR]:虚拟现实游戏套件(VRGK)
https://www.youtube.com/watch?v=YKXwHYGaCqg
2024年1月4日
如果说开发 VR 体验时有一件至关重要的话,那就是虚拟手的有效管理。
在这个频道上,我们专门制作了几个视频来探索这个复杂且有时具有挑战性的主题。
结论很明确:尽管这是一个困难的领域,但有商业解决方案可以提供合理的答案。
其中脱颖而出的解决方案之一无疑是 Divor 的“虚拟现实游戏套件”,或者更广为人知的名称为 VRGK。
该套件价格实惠,解决了手物理和与环境中物体有效交互等关键问题。
它显着节省了时间和精力,极大地提高了体验的整体质量。
很遗憾,随着虚幻引擎 5 的到来,开发人员决定不再继续该项目。
从他们的角度来看,维护该项目所需的工作量巨大且无利可图。然而,由于社区的努力,Divor 被说服提供社区版本。
这将允许其他人继续他们的工作,幸运的是,这正是发生的事情。
利用三智者季节,还有什么比在我们的项目中使用此套件更好的礼物呢?
此外,我们将着手做出一些小牺牲,以使用 MetaXR 插件将其移植到最新版本的虚幻引擎。
参考资料:
▶ 立体工作室:https://stereoopticstudios.com/
▶ VRGK - 虚拟现实游戏套件 v3.0:https://www.unrealengine.com/marketpl...
▶ 最终公告: https: //redirect.epicgames.com/?redir。 ..
▶ VRGK-社区:https://github.com/VRGK-Community
▶ 社区不和谐: /discord
▶ 旧版文档 PDF: https://divivor.itch.io/legacy-docs(密码:legacydocs) ▶ Mozilla 公共许可证 (MPL):https: //www.mozilla.org/en-US/MPL/2.0 /
VR手柄按键 Vive 和 Oculus
https://www.rstk.cn/news/729695.html?action=onClick
跳跃 右手面板下键位
VRGK 添加Vive按键输入
TPS 和 VRPawn 惯性作用inertia
1,平板移动 setActorLocation 开关Teleport
2,平板移动 addWorldOffset 开关Teleport
1-1平板使用setActorLocation进行位移,Teleport为False,TPS正常跟随移动,VRPawn和物理Cube会有移动的惯性动量,平板速度再快则会甩出去
1-2平板使用setActorLocation进行位移,Teleport为True, TPS正常跟随移动,VRPawn和物理Cube则呆在原地不随板子移动
2-1平板使用setActorLocation进行位移,Teleport为False,碰撞体包裹中的物体,TPS和静态物体会两倍速位移,原因是他们已经在随板子移动,又添加了移动增量,如果物理盒子加了overlap事件,则也会2倍数位移
VRPawn和物理盒子则带着惯性动量跟随板子移动
2-2Teleport为True,物理盒子如果不加overlap,则不移动,加了overlap则随板子位移,TPS和静态物体二倍数,VRpawn不移动
2-3Teleport为False,碰撞体的offset的Teleport为true,同2-1
2-4Teleport为True,碰撞体的offset的Teleport为true,同2-2
直升机位移最好使用event tick,否则vrpawn用的eventTick不能同步
即使设置0.01进行位移,vrpawn丢帧导致位移错误
Review项目
GameInstance
运行游戏后只有一个GameInstance
EventGraph 初始化,读取持久存档和全局设置;关闭时,保存存档;关卡启动时,初始化声音
PersistentSaveGameGraph 存档模块,有则读取,无则新建BP_PersistentSaveGameObject对象
SettingsGraph BPO_Settings对象的初始化,并通过settings对象进行参数调用和事件分发监听绑定
Settings通过方法获取存档配置中的选项
需要调用Setting对象的时候,使用自定义蓝图函数库 BluePrintFunctionLibrary中的Get BPO Game Setting获取Setting对象
BPO_Setting中的方法
蓝图函数库中从GameInstance对象中获取其成员Setting实例对象
蓝图函数库中获取GameInstance实例对象
Settings事件分发的call和bind
获取setting对象后,绑定监听事件分发
UI调用setting对象的方法,其方法中调用了call
绑定监听在具体对象中实现
BPO_Setting中的定义了方法对事件分发进行了Call调用
UI中调用了setting对象的方法
存档对象 BP_PersistentSaveGame
设置对象 BPO_Settings
GameMode
每个关卡都有单独的GameMode
如前后关卡中GameMode下PlayerController 配置相同时,上个关卡中PlayerController 不会进行销毁
Content/VRGK/Blueprints/Core
父类:BP_VRGameModeBase 并实现接口 BPI_VRGameMode
GameMode使用:子类:BP_DemoGameMode
初始化创建对象: BP_MenuController菜单UI、BP_VRSpectator观察着、BP_PlayerVignette黑圈视野、BP_CameraWaterOverlay水下视野
BP_VRSubtitles副标题UI
打开Menu菜单时,专门生成一个VRPawn射线控制UI
通过接口返回对象来调用GameMode中创建的一系列对象
Menu面板
朝向和pawnCamera一致
包裹材质球
Set custom primitive Data Float,Mesh的Render中配置,材质球中也勾选配置
自定义基元数据配置alpha值,这么使用是为了优化减少DrawCall
勾上Use Custom Primitive Data则这个参数就不可在材质里修改默认值,同样材质实例里也找不到该参数
传递参数给Custom Primitive Data,编辑器面板在Rendering下面的Custom Primitive Data可以增删相应的数据,蓝图中,有Set Custom Primitive Data从float到Vector4四个函数
开启移动端Dynamic Instance,需要在项目配置ini中加一行,把r.Mobile.SupportGPUScene设为1
如何使用 Custom Primitive Data
https://zhuanlan.zhihu.com/p/83529624
优化UE4性能 、减少DrawCall,材质中使用自定义基元数据
https://zhuanlan.zhihu.com/p/215545723
Spectator 观察者OB模式
切换观察镜头Type,镜头捕获画面2D组件
Vignette 黑圈视野 虚影效果
通过黑盒子实现
瞬移,Instant为true,小黑盒被隐藏了则显示出来,小黑圈播放从无到有的动画(延长版),0.05s后,执行0.3s的小黑圈淡出,并隐藏小黑盒
移动,Instant为false,小黑盒被隐藏了就显示小黑盒,并播放淡入动画0.3s复现黑圈;
如果持续移动,则一直执行显示小黑盒,小黑盒已经显示的状态就不继续执行;
最后停止移动执行0.3s的小黑圈淡出,并隐藏小黑盒
黑圈材质为自定义基元数据处理淡入淡出的alpha值
临时显示视野黑圈,在VRGamePawn中被调用
左手前后左右移动
右手左右转向
瞬移 【唯一的瞬息true】
每帧调用 根据角色速度值
水下镜头 BP_CameraWaterOverlay
自定义基元数据 设置水材质
绑定监听分发事件OnTrackerStateUpdate
添加自定义组件BPC_TaggedComponentOverlapTracker,用于注册原始组件Overlap的Tracker事件
在自定义组件中,OverlapBegin添加组件到数组,OverlapEnd则从数组中移除触碰的组件
副标题 BP_VRSubtitles
widgetRoot 绝对值scale
scene 绝对坐标
定时器每0.2s执行,判断当前scene值推断的widgetroot值是否大于30位移或15角度偏移,
是则进行0.4s一次的旋转值lerp插值更新,把widgetroot的旋转值渐变到scene推断的位置
eventtick 每帧同步scene组件坐标值为actor坐标值
这个蓝图对象 attach吸附到camera上,但是scene节点为绝对坐标系,需要动态修改。
如果是scene节点是相对坐标系则实时跟随镜头移动,无法实现延迟转向。
定时器0.2s执行,获取当前吸附在Camera节点上的自身actor的坐标值,并计算前方80cm 下方25cm处的WidgetRoot坐标值
吸附在镜头上
FPS高度96的时候
Camera相对高度64,绝对高度160,所以umg对象高度也是160
UI是进入房间,触碰overlapBegin时执行
Pawn
父类:Content/VRGK/Blueprints/Player/PlayCore/BP_VRBasePawn
子类:Content/VRGK/Blueprints/Player/PlayCore/BP_VRGamePawn
GameMode内使用:子类:Content/VRGK/Blueprints/Player/GamePawns/BP_VRPhysicsPawn
BP_VRBasePawn
VRNotifications 判断头显是否戴上,只有Oculus有返回状态值,steamVR就手动修改返回true
Set Tracking Origin 节点
Origin参数
Floor Level:VR设备中,定位的地面高度,为Z平面
Eye Level:VR设备中,定位的那一刻,头盔的高度,为Z平面
设置跟踪原点为地面 set tracking origin
坐立式体验,则可以设置为eye level
换装功能
1.可通过修改材质实现换装。
2.通过修改Mesh实现换装。1个角色由多个Mesh组成,比如:头,脚,身体,手都是单独的Mesh。它们共用一个骨骼,共用同一个动画蓝图。
如何实现这些Mesh共用同一个动画蓝图呢,参照如下图。
SetMasterPoseComponent
所有的SkeletalMesh共用Mesh节点的动画蓝图。共用动画蓝图节约资源
角色材质通道
Mesh材质球通道,0身体、1logo、2手、3头
Spectator 材质球通道2个,1为胸口logo
消防员材质球通道
0-脸 1-眼 2-脚 3-手和胸 4-玻璃面罩 5-口罩呼吸机 6-头盔
工具类
BPFL_GlobalFunctions
动画Anim
标准站立Standing添加了Notify ResetFootPlacement
LeftFootPlaced
左脚放置之后抬起来,
右脚收回
手指动作
动画蓝图 姿势数据
Oculus Android运行
1、只剩双手,身体材质被设置为透明,需要排查
因为源码改为消防员隐藏头部的0通道,变成小白人0通道隐藏身体
2、 OculusLink运行串流 与HTC vive一样执行;
安卓模式:
但是主Map(Map_MuseumV3) 直接Launch Android Quest不行,从其他地图Launch后再进入主Map就可以。
打包同理
3. 直接打包到手机报错 Failed to open descriptor file .../.../.../VRGK_V3/VRGK_V3.uproject
主Map报错:
LogPlayLevel: Error: 08-20 22:38:37.378 5952 5985 D UE4 : [2023.08.20-14.38.37:378][ 0]LogStreaming: Error: Couldn't find file for package /Script/SteamVRInputDevice requested by async loading code. NameToLoad: /Script/SteamVRInputDevice
LogPlayLevel: Error: 08-20 22:38:37.378 5952 5985 D UE4 : [2023.08.20-14.38.37:378][ 0]LogStreaming: Error: Found 1 dependent packages...
LogPlayLevel: Error: 08-20 22:38:37.378 5952 5985 D UE4 : [2023.08.20-14.38.37:378][ 0]LogStreaming: Error: /Game/VRGK/Blueprints/Player/PlayerCore/BP_VRGamePawn
LogPlayLevel: Error: 08-20 22:38:38.463 5952 5985 D UE4 : [2023.08.20-14.38.38:463][ 0]LogProperty: Error: Struct type unknown for property 'StructProperty /Game/VRGK/Blueprints/Player/PlayerCore/BP_VRGamePawn.BP_VRGamePawn_C:SetSteamVRHandCurls:CallFunc_GetFingerCurlsAndSplays_FingerCurls'; perhaps the USTRUCT() was renamed or deleted?
LogPlayLevel: Error: 08-20 22:38:38.463 5952 5985 D UE4 : [2023.08.20-14.38.38:463][ 0]LogProperty: Error: Struct type unknown for property 'StructProperty /Game/VRGK/Blueprints/Player/PlayerCore/BP_VRGamePawn.BP_VRGamePawn_C:SetSteamVRHandCurls:CallFunc_GetFingerCurlsAndSplays_FingerSplays'; perhaps the USTRUCT() was renamed or deleted?
=== Handled ensure: ===
LogPlayLevel: Error: 08-21 18:16:18.725 21242 21468 D UE4 : [2023.08.21-10.16.18:725][ 0]LogOutputDevice: Error:
LogPlayLevel: Error: 08-21 18:16:18.725 21242 21468 D UE4 : [2023.08.21-10.16.18:725][ 0]LogOutputDevice: Error: Ensure condition failed: (ImageCreateInfo.usage & VK_IMAGE_USAGE_STORAGE_BIT) == 0 [File:D:/Build/++UE4/Sync/Engine/Source/Runtime/VulkanRHI/Private/VulkanTexture.cpp] [Line: 433]
=== Critical error: ===
LogPlayLevel: Error: 08-21 18:16:18.779 21242 21468 D UE4 : [2023.08.21-10.16.18:779][ 0]LogAndroid: Error:
LogPlayLevel: Error: 08-21 18:16:18.779 21242 21468 D UE4 : [2023.08.21-10.16.18:779][ 0]LogAndroid: Error: Assertion failed: CurrentShadingPath < EShadingPath::Num [File:D:/Build/++UE4/Sync/Engine/Source/Runtime/Renderer/Private/PostProcess/SceneRenderTargets.h] [Line: 601]
LogPlayLevel: Error: 08-21 18:16:18.779 21242 21468 D UE4 : [2023.08.21-10.16.18:779][ 0]LogAndroid: Error:
LogPlayLevel: Error: 08-21 18:16:18.779 21242 21468 D UE4 : [2023.08.21-10.16.18:779][ 0]LogAndroid: Error: [Callstack] 0x00000000C4580014 libUE4.so(0x000000000A77E014)!FSceneRenderTargets::GetSceneColorForCurrentShadingPath() const []
LogPlayLevel: Error: 08-21 18:16:18.779 21242 21468 D UE4 : [2023.08.21-10.16.18:779][ 0]LogAndroid: Error: [Callstack] 0x00000000C4588FC4 libUE4.so(0x000000000A786FC4) []
LogPlayLevel: Error: 08-21 18:16:18.780 21242 21468 D UE4 : [2023.08.21-10.16.18:779][ 0]LogAndroid: Error: [Callstack] 0x00000000C435D4A0 libUE4.so(0x000000000A55B4A0)!SetupMobileBasePassUniformParameters(FRHICommandListImmediate&, FViewInfo const&, bool, bool, FMobileBasePassUniformParameters&) []
原理
【报错】如果Oculus Android运行
从Map_MuseumV3进入,因为地图过大,
读取设备信息还是SteamVR,其他C++资源也未能正确读取,所以报错。从其他地图跳转则正常;
每帧调用,OculusAndroid启动时,初始帧调用默认SteamVR
【无效】添加延迟,地图太大时,读取不到OculusHMD
【无效】添加打包配置,因为根本不是SteamVR
Packing -> Additional Asset Directories to Cook
/Script/SteamVRInputDevice
(有效)启动先加载小地图,再跳转加载大地图
(无效)直接解决方法
Additional Asset Directories to Cook
https://forums.unrealengine.com/t/couldnt-find-file-for-package/447179
for anyone trying to reference a directory inside a Plugin, you can use
UE4: ./../Plugins/ThePlugin/Content/TheDirectory
UE5: /Game/./../Plugins/ThePlugin/Content/TheDirectory
https://blog.csdn.net/qq_18349021/article/details/125321726
Plugins
对比串流和安卓
1.现在OculusLink有线串流启动和steamVR效果是一样的,就是Oculus内的画质比htc vive糊一点,所有地图都正常。
2.然后对于头显android调试运行就离谱,
vrgk_v3默认主地图,头显安卓启动失败;
vrgk_v2默认主地图就可以直接头显安卓启动。
但是如果先头显启动测试地图,再在游戏内跳转回v3的主地图就可以正常运行。
3.安卓启动的测试地图 ,Oculus镜头内直升机和瀑布特效正常;但是森林着火地图点击launch android,项目奔溃。
还未尝试头显启动测试地图再跳转森林着火地图。
4.如果打包到手机,即使是空白地图,手机apk启动也是报错,估计和game instance有关
5 所以真开发打包安卓,要想运行,效果要低,主地图不能大。