当前位置: 首页 > news >正文

VR大空间资料 04 —— VRAF使用体验和源码分析

自用文档,UE4.27 UE5.4项目 HTC Vive VR和Pico4UE  

可SteamVR串流 HTC ViveVR、OculusQuest2、Pico4UE设备

可OpenXR串流Pico4UE设备

可打包apk运行于OculusQuest2、Pico4UE设备

官网地址

fab地址  https://www.fab.com/zh-cn/listings/c29a61c5-c337-4b07-9ff7-6ed9788619e3

项目地址 https://www.unrealengine.com/marketplace/zh-CN/product/advanced-vr-framework

商城店家1 https://www.unrealengine.com/marketplace/zh-CN/profile/SSZ+Canada+Inc

商城店家2 https://www.unrealengine.com/marketplace/zh-CN/profile/Human+Codeable

官方文档 https://humancodeable.com/documentation-main/

Yutube频道 https://www.youtube.com/channel/UC-21apdXIhGS_hYVsRll4UQ

官方引导页 https://linktr.ee/humancodeable (官方打包文件无法下载)

Map_Example_Comp地图,官方默认ProjectSetting

SteamVR分辨率 150% 2460x2740:20帧 此时开启DLSS:30帧

SteamVR分辨率 100% 2016x2240:30帧 此时开启DLSS:45帧

SM5→SM6→SM6+VirturalShadowMap→+Lumen

VR帧率30→26→20→0(运行立刻OOM),

PC帧率96→76→70→45帧(1秒后内存OOM)

TSR→TAA→FXAA→MXAA

VR帧率30→30(远处字体闪烁)→30(远处近处字体闪烁)→30(远处近处都有锯齿感)

PC帧率96→120→104→106

Map_Example_Comp地图开启 Virtural Shadow Map(依赖SM6) 可以修复UE5.4左右眼阴影不同步的Bug

SteamVR分辨率 100% 2016x2240:20帧 此时开启DLSS:30帧

https://vreue4.com/recent-posts

advanced session plugin

A Virtual Reality Tool Kit

DLC

AFU - Smartwatch - VR (依赖于4.1版本 和 Oculus)

https://www.youtube.com/watch?v=cGvVouBurPM

Version

4.20-4.23: AVRFramework 2.1 AVRFramework

4.24-4.25: AVRFramework 3.1 AVRFramework

4.26: AdvancedFramework 4.1 AFCore

5.0: AdvancedFramework 5.0 AFCore

官方文档

官方文档 https://humancodeable.com/documentation-main/

file:///F:/_VR/AVRFramework%E2%80%94%E2%80%94PDF/Documentation_AFCore_4.1.pdf

不需要Nav自动寻路组件

VRHand模型手掌长度20cm 170cm高度

Epic默认VRHand手掌27cm 190cm高度

还可以, 个人推荐vrep框架,免费开源,且随UE版本跟新

vraf有局域网功能,能打包安卓和平板,基本vr抓取触碰事件有组件填动画Transform参数就行,一些宏函数可以抄来用

没有全身body,可以结合mimic ik body,

商城只更新到5.2版本,最近一次更新是从epic上传到fab。

5.3因为UI控件的父类中不能使用Handle异步线程,需要自己改一改

针对大空间需要调整方法TeleportCharacter传参不旋转,和胶囊体不同步头显坐标

vraf官方youtube网址禁止评论,dlc包放自己官网卖。

后处理花屏

如果Windows平台设置中的RHI改为 dx12,再把Custom Depth-Stencil Pass的【EnabledWithStencil】改为【Enabled】就会导致手柄射线的边框错误成后处理乱码

RHI改为 dx11时,配合 Custom Depth-Stencil Pass的【Enabled】边框颜色不显示。

模型切换

默认OpenXR插件

UE的MotionControllerComp,会根据VR运行环境,配置不同的模型

OpenXR---HTCVive 或者 Quest 2模型

OpenXR + PicoOpenXR Oculus Quest1模型

PicoXR + PDC Quest 2模型(因为默认BP_MotionController 使用这个模型,模板源码左右手模型颠倒,需要自行修正)

BP_MotionController初始化时,把自身这个自定义手柄模型的Acotr 吸附到 MotionControllerComp

如果不执行

基本为True,隐藏自定义ControllerMesh模型。

如果不隐藏,则自定义模型白色quest2和MotionControllerComp的黑色Oculus1模型重叠显示

UE5.3可以处理隐藏官方默认的MotionControllerComp的设备模型,替换为自定义模型。

HTC和Oculus的手柄模型怎么判断切换模型显示,按键通过CompController的Preset文件配置

VRAF官方案例的模型在建模阶段就考虑了和VR游玩是的角度配置

Vive是平的 正X朝向

Oculus是有倾斜角度

Pico 则是把Occulus模型绕y轴转30°

左手Invert Scale-Z轴-1,右手Invert Rotation-y=50 左手负50

Lumen

如果要 lumen 开启,还需要开启Generate Mesh Distance Fidled 或者 Support HardwareRayTracing

如果开启硬件光追,还需要开启skincache

Lumen + 硬件光追

前向渲染 打包Android用

Forward Shading‌是一种在计算机图形中常用的渲染技术,主要用于实时渲染场景中的物体。其基本原理是在每个光源下单独渲染场景中的每个物体,即对每个光源和每个物体进行独立的渲染处理。

基本原理

在Forward Rendering中,首先渲染场景中的所有光源,然后对每个物体应用这些光源的效果。具体步骤如下:
  1. 光源渲染‌:首先,对场景中的每个光源进行渲染,生成光照贴图或光照数据。
  2. 物体渲染‌:接着,对场景中的每个物体应用这些光照数据,生成最终的图像。

优缺点

优点‌:
  • 直观易懂‌:Forward Shading的原理简单直观,容易实现和理解。
  • 灵活性强‌:适用于各种类型的光源和物体,特别是对于静态或变化不频繁的光源效果较好。
缺点‌:
  • 性能问题‌:对于大量光源和复杂场景,Forward Shading会导致大量的重复计算和渲染,影响性能。
  • 内存占用‌:需要存储大量的光照贴图,占用较多的内存和存储空间。

应用场景

Forward Shading适用于以下场景:
  • 静态或变化不频繁的光源‌:由于不需要频繁更新光照数据,静态光源可以有效地利用Forward Shading。
  • 复杂场景‌:对于包含大量静态或变化不频繁物体的场景,Forward Shading可以提供较好的渲染效果。

Separate Translucency

PDA设置

项目设置中有PDA,CompControl也有PDA手柄配置

打包Oculus

勾选Meta Quest设备,否则会以观看平板的模式运行游戏

AI移动

需要把Nav Volume通过Ctrl M 改放在 Persistent地图,才能在Persistent运行时,成功执行AI寻路,否则会aborted

如果Nav只放在大厅地图,Persistent运行时失效。

如果Nav放在Mesh地图时,Manager运行也时失效

【错误记录】

Teleport瞬移是将Camera移动到目标位置,此时Pawn位置有相对偏移

沙漠地图不知道为啥瞬移过去时,会仿佛重置头显设备。 向量Camera - 向量Pawn + 向量Pawn

因为默认使用瞬移,导致Camera位置和Pawn位置重叠

1.BP_PlayerControllerMain Spawn PlayingPawn,此时Camera和Pawn位置是正确的。

2.BP_PlayerControllerMain Spawn BP_Transition时传参PlayingPawn,BP_Transition小黑盒Begin时执行角色Teleport到空中小黑盒,此时的 PlayingPawn时Camera和Pawn位置是正确的。

3.瞬移到小黑盒中心结束后,调用“过渡结束”事件分发,绑定在BP_PlayerControllerMain。

4.从小黑盒瞬移到场景 默认地图时可以匹配,Landscape位置不对。

因为框架源码设置了根据头显坐标重置了胶囊体位置

BP_Pawn_Base中

子类BP Pawn VR重写

Bug 胶囊体朝向

框架默认启动时,以头显朝向为正北 正X方向,因为根据目的地旋转值Set Controller Rotation。

修改BP_Transition和BP_PlayerPosition的UseRotation为false

CSDN文档

https://blog.csdn.net/weixin_55901138/article/details/138162643

Select & Grab Component 选中和抓起组件

https://blog.csdn.net/weixin_55901138/article/details/138541672

Latch Component 吸附组件

https://blog.csdn.net/weixin_55901138/article/details/138626752

Gaze Component 关注进度条组件

https://blog.csdn.net/weixin_55901138/article/details/138720887

Anchor Component 锚点吸附组件

MotionController

MotionControllerComponent的display_device_model在UE5.4时因为过时被彻底移除,UE5.3还能使用,但是有警告,没有影响,手动修改模型的显示和隐藏即可

https://dev.epicgames.com/documentation/en-us/unreal-engine/python-api/class/MotionControllerComponent?application_version=5.2

display_device_model (bool): [Read-Write] Display Device Model: Used to automatically render a model associated with the set hand.

display_device_model (bool): [Read-Write] deprecated: bDisplayDeviceModel is deprecated.

Please use the XRDeviceVisualizationComponent for rendering instead.


BP_PawnVR 在OnPossess时,获取BP_PlayerController_Main,并调用父类BP_PawnBased的方法ClientInitializePawn执行客户端角色初始化,

BP_Pawn继续在ClientInitializePawn方法中执行客户端角色初始化,继续调用Server_PrepareVRPawn执行服务器方法调用SwitchControllers创建左右手控制器

创建自定义Actor -- BP_MotionController -- BP_MotionController_Controller_Left 手柄射线模式

或者 -- BP_MotionController_Hands_Left 手掌拟真模式

BP_PawnVR初始化创建自定义控制器BP_MotionController时,传参官方组件MotionControllerComp变量(display_device_model变量过时)

BP_MotionController_Controller_Right 挂载ChildActorComp节点 BP_MComp_Laser 实现射线抓取功能、UI射线模拟鼠标点击

BP_MotionController_Hands_Right 挂载ChildActorComp节点 BP_MComp_Hand_Grab 实现按键拟真抓取功能

BP_MotionController_Hands_Right 挂载ChildActorComp节点 BP_MComp_Hand_Laser 实现UI射线模拟鼠标点击 Select功能名触发

BP_MComp_Teleport 瞬移功能

BP_MComp_Movement 移动功能

display_device_model相关

如果是是手柄模型,则影响显示隐藏;手掌模型不影响

手柄震动 Haptics

"SetHaptics"

Comp组件

自定义ActorComponent组件,物体可以被互动的功能模块化

功能分类

Info

Comp_PlayerInfo_Basic 被用于BP_PlayerState_Main、Widget_Multiplayer_Host_Simple、Widget_NameTag

Interaction

Comp_Gaze

ActorComponent组件

交互地图中,简单凝视案例 BP_GazeView 和其子类凝视文本动画 BP_GazeView_DemoText 都依赖了Comp_Gaze组件

BP_GazeView凝视出现文本动画 调用 CompGaze的GazeView回调,根据枚举执行容器内的组件们 显示/隐藏、缩放、位移

Comp_Gaze_Comp

Progressbar:

Gaze组件被目光/光标聚焦时,会出现一个逐渐增长的进度条用于提示用户已经开始聚焦,当进度条满格后就会触发交互事件。Progressbar这一栏参数用于调整Gaze交互的触发时间与进度条的样式,UI有两种预设两种预设样式,环状进度条与横条,如果用户要自行设计进度条,需要继承Widget_GazeIndicator类:

Timeout Gaze:不继续凝视0.2s后 停止凝视

Progress Duration: 设定从聚焦开始到触发交互需要目光停留的时间

开始调用输出Start,连续调用输出Update,直到停止调用后,等待延迟Timeout ,最后再输出End

Settings:

Component Definition:

ComponentTagToSearchFor:

添加Gaze组件交互事件联动的组件的Tag,通常会与Switch组件交互,Switch组件再与其他功能组件进行交互。

ActorsToTrigger:

添加场景中产生交互的Actor对象引用,Actor对象的组件必须包含上一栏中的Tag。若是在自身Actor中进行通信,则只需要勾选TriggerAlsoSelf即可。

Toggle:

表明交互事件触发时会交替设置交互组件的Set/Unset状态。

Component Tag to Gaze at:

用于设置用户聚焦在哪个Mesh上,默认为None时表明用户的目光聚焦到整个Actor(可能包含多个mesh)都能触发Gaze事件,若希望在聚焦到某部分Mesh时才触发聚焦事件,则需要在Mesh上添加Tag并将Tag填入该参数栏

Comp_TouchSnap

自定义拾取物品后触碰显示进度条,进度条完成时执行吸附逻辑

Comp_TouchSimulate

自定义触摸物体时显示进度条,进度条完成可自定义调用执行语言字幕播放、下一步逻辑等事件。

组件挂载在可触摸的物体上,PC端通过按T键位进行持续屏幕中心射线检测,扫描到物体时显示圆圈进度条,

组件中创建进度条BP_GazeIndicator的子类BP_ProgressCircle,其中挂载了Wiget组件。BP_GazeIndicator设置了进度条回调等事件分发回调

VR端则手心射线检测触摸(暂未实现)

Comp_VoiceCaption

自定义音频语音字幕组件,挂载在角色身上,定时器修改UI窗口坐标

Comp_Grab

要被拾取的物体,添加CompGrab这个ActorComponent组件,

组件中携带者InteractorInfo交互信息键值对,用于调用每个交互Actor的接口抓取和释放

屏幕和移动端版本,因为没有Controller控制器手柄,所以BP_Pawn_Base_Screen实现了接口Interface_GrabbingActor

VR版本,手柄控制器挂载了BP_MComp_Laser这个Actor作为ChildActorComp,其实现了接口Interface_GrabbingActor

VR版本,手掌控制器挂载了BP_MComp_Hand_Grab这个Actor作为ChildActorComp,其实现了接口Interface_GrabbingActor

参数说明

GrabType:

按照官方的文档,抓取类型有普通模式与使用物理柄的模式。在桌面端测试中两个模式没有看出太大的差别,

模板中的Pawn类中集成了使用Physics Handle抓取的逻辑。默认使用normal模式即可,Physic Handle可能是类似隔空取物的模式

Release Type:

是否开启物理模拟。当你选择了Free Placement,即松手后物体停留在松手时的位置,即使用户在运行前手动将StaticMesh或SkeletalMesh的物理模拟打开,模型仍然不会开启物理模拟。相应的,当设定到Physics模式时,物体就自动开启了物理模拟

Should Keep Upright:

定义了当物体被拿起时是否自动将物体旋转到自身Z轴与世界Z轴平行。

在VR项目中,如果想让物体模拟被手拿起来的效果,请把这一项参数关闭

Snap:

参数只有在使用VR模式且使用BP_MComp_Laser抓取时才会使用到。

开启Snap后,当用户使用Laser抓取物体时,物体会自动吸附到手柄处,吸附后的物体旋转需要玩家自行在Relative Controller Position中进行定义

Conditions

参数定义的是Grab组件的一些限制条件。

Canbe Picked UP: 表明是否开启Grab功能

Should Auto Pickup: 这一条件只适用于VR项目,它表明Actor在VR手柄接近后是否被自动拾取

Max Distance to Socket: 规定了物体能被拾取的最大距离

Grab Attached Actor Instead: 这个笔者还未测试过,猜测打开后即使松开抓握键物体也不会掉落

Grab Tag: 当Actor中不止一个StaticMesh时,可以对能够被抓取的Mesh添加自定义Tag并将Tag填写入该栏中,这样只有含有对应Tag的Static Mesh能够被抓取起来。

Allow MultiGrab & Allow Pickup if Already Picked Up: 这两个选项需要同时打开才能实现

Keys这一栏参数笔者认为是非常重要的,有使用过VRA模板的用户会发现当用户用手柄射线抓握了物品后,手柄的X轴和Y轴绑定的转向/移动事件会被重载为将被抓握的物体旋转/前后移动。然而当我们实际项目中,很多需求是需要拿起物品进行移动的,解决这一问题的关键就在于合理设定Keys这一栏参数。

Grab组件能够重写手柄的事件,预设的手柄事件如下:

AllKeys:

参数为true时,当用户拾取Actor后,Grab组件就会重写上图手柄的事件。

此时VR模式下的移动事件就会被Blocked,因此当用户有拿起物体移动的需求时,AllKeys参数需要为False.

OccuiedKeys Array:

有时当用户拿起物体后,物体含有特殊功能需要通过手柄按键触发时,可以在Array中添加需要重写的手柄输入事件。

例如当用户拿起枪,手柄按下Trigger时就应该能够发射子弹,此时就可以在Array中添加Trigger,然后重写Grab组件的Grab Trigger Axis事件即可。

伪代码

Allkeys为False时,VR手掌抓着物体时才能正常使用控制器原本配置的功能

例如:瞬移

本蓝图物体被抓起后 重定向Trigger功能

【注意】官方默认版本为 Trigger映射Select功能,所以Grip映射Grab,简单配置Trigger占用,即可后续模拟扳机开枪功能

现改为Trigger隐射Grab功能,修改BP_MComp_Hand的FunctionInput源码,目的Trigger松开按键时不丢开物品

如果CompGrab添加了Face01的占用

则在抓起物品时,无法使用控制器原本配置的Teleport瞬移功能

如果抓取模型后,想吸附到目标位置时,不需要虚影功能则断开TrytoSpawnSnappingHelper连接,

此时吸附功能也失效,需要用老版本的球形碰撞体Overlap检测的Attach吸附逻辑。

【解决】简单处理,继续连接执行TrytoSpawnSnappingHelper,修改源码:

添加CompGrab.Search变量配置,创建BP_HelperSnapping时输入配置,关闭Search则关闭每帧搜索设置虚影模型位置,

CompGrab 自定义新增条件变量SerachToShowHoloGhost。

抓取后,靠近目标位置,此时松手后,物体吸附目标

改为:抓取后,靠近目标位置,不松手等待2秒,出现进度条,进度条结束自动松手+物体自动吸附目标

CompGrab.SnapActor 调用 CompConnector.AttachConnectorToActor 吸附到锚点

松手时,判断是否有吸附虚影提示,有则物体位移到虚影Holo处,位移动画期间禁止拾取,绑定占用吸附目标锚点(避免多个把手同时送手吸附),

物品位移到虚影位置时 绑定调用吸附完成回调,执行松开物品和Attach物品到目标。

Comp_Latch

Comp_Latch_Drag

Comp_Latch_Physics

Comp_Latch_Simple

Comp_Overlap

Comp_Overlap_Comp

Comp_Overlap_Drag

Comp_Select

Comp_Select_Comp BP_Table_SelectExample

Comp_Select_SelectionWindow

Comp_Teleport

Misc

Comp_Delete

Comp_LineMeshComponent

Comp_Mount

Comp_Orbit

Comp_SpawnActor

Comp_SpawnLocation

Comp_Spectator

Comp_Video

Multiplayer

Comp_Replication

Comp_Replication_Actor

Comp_Replication_Component

Comp_RPC

Pawn

Comp_Controls

Comp_Touch 触摸组件提供给BP_Pawn_Mobile调用

Snapping

CompAnchor 挂载在要吸附的基底模型位置,其中创建了BP_Helper_Anchor 用于给吸附帮助的球形检测

CompGrab 添加在可拾取的物体,其中创建了BP_Helper_Snapping

CompConnector 挂载在可拾取的物体,被BP_Helper_Snapping每帧调用方法 进行球形检测目标是否有BP_Helper_Anchor

Comp_Anchor

父类StaticMeshComponent,设置吸附模型的锚点

吸附时的逻辑:添加CompAnchor的ActorGotAttached事件分发的绑定

通过在Comp_Connector_Anchor中,调用CompAnchor的AttachActorToAnchor,再Call这个ActorGotAttached事件分发

需要添加在物体将要吸附在的Actor上,相当于一个吸附的基底

参数说明

Anchor Deactivated:

该bool参数用于开启/关闭Connector组件,当bool为true时带有Anchor组件的物体将无法与该connector进行交互,参数默认是false。

Connector IDs to Allow:

需要将吸附在Connector位置的Anchor Comp的ID填入该参数栏中,这样两个组件才能互相通信实现吸附交互。

Connector should attach:

该bool参数用于设定当开启了物理模拟的Anchor物体吸附在Connector上时是否继续持续吸附在Connector上。

如果为false,当connector倾斜时或物体收到物理体影响时,吸附的物体会因为重力掉下。

确保角色在释放后保持相互连接。如果未启用ConnectorShouldAttach,则当物理功能被激活时,连接的角色可能会在折断后掉到地上。

Sphere Radius:

该参数决定了能够检测到Anchor组件的球形范围大小

Transform设置:

Anchor组件与Connector组件吸附的方向与位置是根据这两个组件的Location和Rotation决定的,并且吸附后的物体Scale时由Connector的Scale决定的。

官网推荐在Anchor组件上添加一个Arrow组件辅助判断方向,这两个组件的吸附的方式是两个组件的X轴相对地吸附

Comp_Attach

父类ActorComponent,

被用于收音机本体 和 BP_PawnBase

可以用于吸附完成事件回调,Attach时获取吸附的Actor对象

【疑问】在收音机的这个组件删除了,不影响抓取吸附,可能因为CompAnchorHandle也有attach回调事件

Comp_Connector
Comp_Connector_Anchor

组件需要放置在被抓起的Actor上,Anchor组件与Grab组件之间不需要额外设置,

并且只有当物体被CompGrab抓取后才会触发Anchor组件与Connector组件之间的识别

参数说明

ConnectorID:

需要用户自行添加一个自定义的ID,用于与对应的connector进行吸附的识别。

Search Radius&Distance:

Anchor组件检测Connector组件的范围半径与距离,结合起来类似以Anchor组件为原点的一个胶囊体范围进行检测。

Comp_Anchor的Location与Rotation调整:

Anchor组件的位置与旋转与Connector的组件的位置与旋转决定了物体吸附在基座上时的位置与旋转。根据Connector组件介绍中的图片进行设置即可

Comp_Connector_Surface

State

Comp_Drag

Comp_Highlight

Comp_Name

Comp_Open

Comp_Percent

Comp_Switch

Comp_Trigger

Comp_Velocity

UI

Comp_HUD

父类ActorComponent

挂载在PC角色

Comp_PawnUI

父类ActorComponent

挂载在VR角色

新增变量 控制是否开启随着延迟跟随头部

自定义事件分发WidgetCommandClient,(Use to implement replicable widget functionalities.)

这个事件官方demo无绑定,只被自身的ForwardWidgetCommand调用,注意与Comp_Widget的自定义分发事件同名

ForwardWidgetCommand这个事件被BP_PawnUI_Element调用

SpawnElement核心伪代码逻辑

使用方法:获取角色身上挂载的CompPawnUI组件 通过Toggle调用SpawnElement方法创建UI ,显示和销毁切换

也可以直接调用SpawnElement创建UI

帮助节点是否吸附到镜头

Comp_Widget

父类WidgetComponent

挂载在想要显示提示窗口的物体上

CompWidget的事件绑定添加WidgetCommandClient事件分发,根据命令CloseWidget执行关闭窗口

CompWidget自定义方法 SetWidgetClass根据传递的Class创建WidgetBase,并把自身CompWidget传递进去

按钮面板的子类UI都继承于WidgetBase,WidgetBase自定义事件WidgetCommand,调用了CompWiget的自定义事件WidgetCommand

执行命令关闭窗口CloseWidget 或者 切换关卡SwitchLevel

在CompWiget的自定义事件WidgetCommand中,调用了Call WidgetCommand Client分发事件,其绑定在挂载使用了CompWidget的BP蓝图中

挂载CompWidget的蓝图绑定WidgetCommandServer,Actor开启了Replicates, 执行CloseWidget和SwichLevel。

BP_Trigger_Button_Toggle

交互按钮切换器携带组件

Comp_Drag 组件拖拽

Comp_Overlap_Drag 组件重叠拖拽

Comp_Select 组件焦点

Comp_Switch 组件切换

添加控制的Actor和标签

齿轮的组件Comp_Switch Tag值为Cog_SwitchComp(默认是Cog_ActiveComp)

Comp_Open【State】

Tick 进过编辑器Apply之后,先检测到长度,然后移除,最后停止激活

Comp_Drag 【State】

一般与Comp_Latch一起使用,制作拉杆

DragType 决定了运动的形式和方向

Linear Type:主要是在对应的轴上平移。

Angle Type:主要用与旋转类似方向盘,闸门的交互物体,可以在Yaw与Roll方向上的旋转。【为什么没有Pitch】

Spline Type:能够使用spline自定义拖动的路线,灵活地设计交互物体的拖动路径。

Rotation Type:与Angle Type有所区别,只能在VR模式下进行拖动,一般用于制作旋钮的交互。

ValueRange 范围,AngleType为Rotation时用力方向相反?

StartValue 初始值,搭配Applay使用

Snap Type规定了当用户拖动完物体,物体的释放后运动类型。

FreeMovement:该参数表明当用户放手后,物体会固定在放手时的状态不变。

SnapToSegment:该参数表明当用户放手后,物体会恢复到距离当前值最近的设定值。

Reset: 该参数表明当用户放手后,物体会恢复到被拖动前的状态。

SnappingSpeed: 该参数设定了用户释放物体后,物体Snap到某一值时运动的速度

Follow Speed: 该参数设定了交互物体跟随用户手柄运动的速度

InvertPercent:

该参数要根据用户使用的具体情况来调整,根据物体运动的方向不同,物体走过规定路径/角度的百分比值会变化,例如事例中旋转闸门,我们希望顺时针旋转时,percent的变化为0-1;在测试中顺时针旋转阀门实际上Percent的变化是1-0,此时我们就需要将InvertPercent参数勾选为true。

SectionSet 数组用于让用户自定义规定当前交互物体可以Snap到的部分有多少块,主要是结合Snap Type参数时使用的

Comp_Latch_Drag【Interaction】

Comp_Drag与Comp_Latch_Drag,当两个组件都设定好了基本参数后,需要让这个两个组件建立起通信

在Comp_Drag组件中,需要设定组件的Component Tags,并且将要控制的Mesh的Tag填入至Component Tag to Control参数栏中。

在Comp_Latch_Drag组件中需要将刚刚设定的Comp_Drag组件的component tag填入至Drag Tag参数栏中,并且将要手部模型要吸附到的Mesh的Tag也填入至Component Tag to Attach To该参数栏中即可。

例如CompDrag自身Tag为Lever_DragComp,需要控制的Mesh的Tag为Mesh_Lever

CompLatchDrag需要配置的DragTag值Lever_DragComp,需要控制的Mesh的Tag为Mesh_Lever

Can Be Latched On To:这个参数用于开关Latch Comp,可以根据用户设定在适当的时候开启与关闭Latch功能。

Max Attach Distance:用户手柄能够触发吸附的最大距离。

Auto Attach:

该参数与上一个参数结合使用,若Auto Attach为True时,用户的手柄进入吸附范围后会自动吸附至交互物体上,若为False则需要用户手动按下抓握键才能够吸附在交互物体上。

Component Tag to Attach To:

这个参数需要填写手部模型需要吸附的模型的Tag名称,配置添加Tag至StaticMesh并在SM上添加手部模型吸附的Socket。

Allow Simulataneous Latching:

这决定了交互物体上是否允许多个用户/控制器进行吸附。

Minimum Detach Distance:用户脱离的最小距离,当用户手柄移到范围外时手部模型将自动脱离交互物体。

手部模型调整

(X=-10.000000,Y=6.000000,Z=-3.000000) 右手HMDOffset默认

(X=-10.000000,Y=-6.000000,Z=-3.000000)

(X=-10.000000,Y=3.000000,Z=-10.000000) y=30° pico右手

Latch组件是通过获取交互物体模型上的Socket位置与Socket Name来进行手部模型的贴合与样式的选择。因此在我们要使用Latch组件时需要对模型进行处理,在对应位置添加有命名规范的插槽

根据官方的视频中的说明可知, 插槽的命名规范是:

第一段必须为L_或R_,代表了左手或右手。后面接00-14的数字,这数字代表模板中手部对应的15种不同的手势姿势。

例如下图中的旋钮模型,官方设定的插槽名称为L_02与R_02,这代表了Latch到旋钮时的手势应该是02号手势。

AttachPoint插槽也是必须要有的插槽,它必须要尽可能的靠近手部模型放置在物体上的位置

 VRA模板中自带的十五种不同的手势,用户可以按需自行配置SocketName进行手势的匹配

ChildAcotrComponent组件

BP_MComp持有MotionControllerComp,用与其子类射线、抓握使用

按键逻辑实现在自定义BP_Motion_Controller_Controller的子类左右手控制器中的挂载节点ChildActorComp,例如BP_MComp_Move

框架自定义Actor:BP_MComp,其子类有BP_MComp_Hand_Grab、BP_MComp_Teleport、BP_MComp_Movement,

每个BP_MComp的子类Actor实现用户操作的逻辑模块化,最后作为ChildActorComponent挂载在BP_MotionController节点。【是否可用SceneComponent作为父类?需要查看源码】

框架自定义Actor:BP_MotionController,其子类有BP_MotionController_Controller、BP_MotionController_Controller_LeftBP_MotionController_Hands_Left

BP_PawnVR初始化创建控制器时,传参官方组件MotionControllerComp变量(display_device_model变量UE5.4过时弃用)

BP_MComp 自定义Actor

BP_MComp_Teleport

BP_MComp_Movement

BP_MComp_Hand_Grab

BP_MComp_Hand_Finger

BP_MComp_Ping

BP_MComp_Hand_Laser

BP_MComp_Laser

只有右手手柄有BP_MComp_Laser 做射线交互,而且右手手柄没有BP_MComp_Hand_Grab,

所以通过射线组件 实现功能Select、Grab、LaserModes、Ping

手柄抓取:Trigger常按后拾取,(Release触发)松开Trigger后则丢弃;Grip侧键点按一次松开,(Press触发)抓取物品吸附到手心,再点按一次Grip侧键(Press触发)丢弃物品

手柄射线如果Trigger常按抓取UI面板的滚动按钮,需要按一下侧键才能松开【Bug】

【修复】更改DA_ControllerVR_VivePreset的 HolddingGrip 为True,

模型抓取可以常按Trigger(Select)拾取,松开按键丢下物品,但是UI滑动按钮通过Trigger(Select)常按后依旧需要点按Grip(Grab)键松开,

模型抓取和UI滑动按钮抓取,都可以通过常按Grip(Grab)拾取,松开按键丢下物品和按钮。

官方代码:射线模式常按拾取物品时,同个手柄调用瞬移,拾取射线变为瞬移射线,自动松手

BP_MComp_Hand_Grab

左右手掌都有BP_MComp_Hand_Grab,

所以通过手掌抓取组件 实现功能Grab

手掌抓取:框架原版只有Grip侧键点按吸附,再点按丢弃,修改DA_Preset配置选项,把Trigger和Grip键位都改为Grab功能。

想要抓取物品时瞬移,物品的CompGrab中的Allkeys为False,取消所有按键占用

【Bug】瞬移射线被拾取物体阻挡,导致抓取时无法瞬移

手掌球形检测通道是Visibility

瞬移射线检测通道是Camera,【修复】所以要抓取的物体Camera通道改为Ignore

【Bug】如果改为常按抓取,右手常按抓取时,右手瞬移键刚按下就把抓取功能松开,左手移动正常。如果左手抓取,右手瞬移正常,左手移动正常。

【修复】BP_MCompTeleport中修改占用AllKeys为False

按键触发瞬移时,默认Allkeys为true,则所有按键都松开了,包括常按抓取键

(BP_MComp_Movement无影响 因为没有移动时替换操作的逻辑)

拖拽拉杆抓取时则出现按下Face01出现瞬移引导射线

远程遥控器抓取时没有影响,因为CompGrab重定向上下左右按键映射

如果AllKeys为False时

添加Trigger 则表示该键要占用 执行松开逻辑

添加Grab 则表示功能要占用 执行松开逻辑

【Bug】当前按键自定义DA配置Trigger和Grip都是Grab时,

如果已经常按后拾取,手里有物体

Grip按下时,Trigger再按下不执行,Trigget松开就调用松手,无法实现Grip拿着枪,Trigger开枪射击

【修复】源码新增判断CompGrab是否占用了Trigger,

如果Trigger占用了,就不执行Trigger和Grip的Grab松开逻辑,改为在CompGrab中Grip调用松手接口

【Bug】如果模型无添加Socket,官方版本为模型吸附到手心时产生一小段位移

【解决】改为在哪按键就在哪抓起来吸附到VR手掌

以VR手掌中心点的位置设置球形圆柱搜索距离

官方 20 改为 1 目的是无需虚空念力抓取

参数说明

伪代码

Actor EventTick 根据是否抓取物品,每帧通过按键数值修改手指头弯曲程度,例:远程遥控器 remote

Actor EventBegin初始化时,

事件SetSearchTickForPickup中用无限循环模拟定时器进行球形检测是否可以拾取物品,定时评率根据手里是否抓着物品动态修改0.4、0.1,

用抓取值判断手掌是否张开,如果张开则Search for Pickup 球形检测手心物品是否可以拾取,CompGrab执行物品高亮,

(如果有自动拾取,则继续调用接口抓取Grabbing Actor Grab Actor实现吸附功能)。

接口实现Grabbing

BP_MComp_Hand_Grab 实现了接口 Interface_GrabbingActor 的 Grabbing Actor Grab Actor方法,(还有射线和PC桌面实现过这个接口方法)

这个接口方法在被扫描时自动抓取时被调用过,

这个接口方法在BP_PawnVR按键事件映射中,通过调用BP_MotionController的KeyInput方法,然后遍历BP_MComp并执行其Function Input方法中被调用,

接口实现时调用了 Check for Grab or Latch 方法,判断传参Actor是否有CompGrab组件,根据SocketName获取手指动作,有则特殊姿势抓取,无则直接抓 GrabActor

GrabActor OnRep_GrabDefinition GompGrab.GrabPressedGompGrab.TrytoSpawnSnappingHelper → CompAnchor/CompConnector锚点吸附逻辑

GrabActor方法中,调用OnRep_GrabDefinition,设置抓取的手指动作、吸附在手掌控制器的点位、是否替换了按键功能(例如抓着枪射击发射子弹),

如果GrabComp的所有者蓝图有开启同步则服务器调用OnRep_GrabDefinition

【疑问】收音机把手没有开启Replicates,但是有Comp_Replication_Actor

GrabDefinition的Set w/Notify 同步方法OnRep_GrabDefinition

调用了Detach for Grab,判断手里是否有东西,是否可以多抓取,调用CompGrab.ReleaseAllGrabbingActors执行松开所有抓取物

实现了抓起物体时是否有PhysicsHandle物理约束,

设置FirstHandle、SecondHandle位置,调用PullActor拉起抓着的物体 移动到手掌的正确位置,

OnRep_GrabDefinition最后调用GompGrab.GrabPressed方法,其中执行了调用抓起物体后的事件分发(绑定在具体的拾取物体蓝图中),物理约束设置,

GompGrab.GrabPressed最后调用GompGrab.TrytoSpawnSnappingHelper,创建吸附帮助,提示用的高亮模型、虚影模型GhostMesh

PullActor方法,目的是使用timeline动画实现 拉起抓着的物体 移动到手掌的正确位置。

OnRep_GrabDefinition调用,即为GrabDefinition的Set w/Notify中调用。

BP_MComp_Hand_Grab 实现了接口 Interface_GrabbingActor 的 Grabbing Actor Release Actor 方法,(还有射线和PC桌面实现过这个接口方法)

这个接口方法在BP_PawnVR按键事件映射中,通过调用BP_MotionController的KeyInput方法,然后遍历BP_MComp并执行其Function Input方法中被调用,

这个接口方法在CompGrab.EventBegin被调用过,初始化绑定销毁时调用该接口

这个接口方法在CompGrab.ReleaseAllGrabbingActors被调用过,

GrabDefinition调用了Detach for Grab,其中调用CompGrab.ReleaseAllGrabbingActors目的是松手释放所有抓取的物体

Detach for Release.Detach from Grabbing Actor 和 Detach for Connector.Detach from Grabbing Actor 被用于齿轮系统案例,齿轮的连接和吸附

AFVR按键映射源码分析

按键逻辑实现在自定义BP_Motion_Controller_Controller的子类,

左右手控制器中的挂载子Actor节点ChildActorComp,

例如BP_MComp_Movement

移动功能按键数据传递

CompControls获取DA_ControllerVR_VivePreset的左右手详细按键

Key:EnumSide

Value:Struct_KeyToFunctionMap

目的是设备按键 映射为自定义功能变量

例如: 圆盘↑键 Face01 映射为 Teleport

ProjectSetting--InputAction设置FaceButton01Right值Vive(R)Trackpad Up

按键触发时映射为左右手的Face01(取自自定义按键枚举Enum_Controller_Buttons)

VRPawn调用CompControls组件方法再映射为功能Teleport(取自DA_ControllerVR_VivePreset)

其中ExecuteControlFunction如果被子类VRPawn执行则优先执行重置、暂停、PawnUI功能名

BP_PawnVR 调用左右手控制器BP_Controller的方法Key Input 传参功能名,目的是MComp执行功能

BP_MotionController 的 KeyInput 按键按下的操作添加到集合(松开移除),遍历挂载子Actor节点BP_MComp,组件执行FunctionInput和KeyPressed(子类重写)

例如Teleport功能实现在BP_MComp的子类Actor:BP_MComp_Teleport,作为ChildActorComp挂载在

自定义手柄控制器BP_MotionController_Controller_Right的节点上,这样左右手可以模块化不同按键功能

也可以最后再在playerPawn中新增按键重定向

BP_VRPawn设置按键事件监听

DA_ControllerVR_VivePreset中按键配置

CompControls中按键映射

默认按钮

FaceButton01 左手上键呼出菜单,右手上键

Y键 飞行

Tab键位,聊天

Ping F键

VOIP Loop L键 网络电话?

Sprint 冲刺 左Shift

跳跃 Jump

控制鼠标 左Alt

Select 鼠标左键拾取

鼠标右键旋转

暂停 P

蹲下Crouch C键位

Input 按键设置

默认常按

MoveRight 和 ThumbstickLeft_XY

Pico Input 按键配置

PDA Vive 对比 Oculus

VRPawn的CompController中配置PDA

DA_ControllerVR_VivePreset 对比 DA_ControllerVR_OculusPreset

瞬移改成按钮松开,瞬移结果面向为手的朝向方向

HTC Vive VR 项目自定义二期按键

抓取功能按键数据传递

ProjectSetting -- InputAction设置按键 Trigger和 Grip

BP_PawnVR 中 设置按键触发时映射为左右手的 Trigger 和 Grip (取自自定义按键枚举Enum_Controller_Buttons)

BP_PawnVR 调用CompControls组件方法再映射为自定义功能名Grab(取自DA_ControllerVR_VivePreset)

其中ExecuteControlFunction如果被子类VRPawn执行则优先执行重置、暂停、PawnUI功能名

BP_PawnVR 调用左右手控制器BP_Controller的方法Key Input 传参功能名,目的是MComp执行功能

BP_MotionController 的 KeyInput 按键按下的操作添加到集合(松开移除),遍历挂载子Actor节点BP_MComp,组件执行FunctionInput和KeyPressed(子类重写)

可以抓起的Actor,添加CompGrab组件(Actor Comp),吸附到基底锚点的点位Comp_Connector_Anchor(SceneComponent)

基底吸附的Actor,吸附锚点点位Comp_Anchor_Antenna(StaticMeshComponent) 添加CompAttach组件,吸附数量(Actor Comp)

BP_MotionController_Hands_Right 挂载ChildActorComp节点 BP_MComp_Hand_Grab(Actor) 实现按键拟真抓取功能

伪代码

BP_VRPawn绑定按键监听并映射为功能名,让 BP_MotionController 的 KeyInput 方法执行按键功能名。

在 BP_MotionController 初始化时,遍历自身挂载的BP_MComp的ActorChildComp,然后再在自身 KeyInput 中循环遍历执行每个BP_MComp.FunctionInput和KeyPressed

左右手手掌控制器挂载 BP_MComp_Hand_Grab,在组件内FunctionInput 执行了Grab方法名,调用了接口Grabbing Actor Grab Actor,

接口实现时调用了Check for Grab Or Latch,方法中调用了GrabActor方法,方法中调用了GrabDefinition的Set w/Notify 同步方法OnRep_GrabDefinition 和 手指动作设置 和 抓取时按键。

同步方法内实现了抓起物体时是否有PhysicsHandle物理约束,

设置FirstHandle、SecondHandle位置,调用PullActor拉起抓着的物体 移动到手掌的正确位置,

最后调用CompGrab.GrabPressed方法,其中执行了调用抓起物体后的事件分发(绑定在具体的拾取物体蓝图中),物理约束设置

最后调用GompGrab.TrytoSpawnSnappingHelper,创建吸附帮助,提示用的高亮模型、虚影模型Ghost

BP_MapInfo

地图数据和Pawn配置

Map_Example_Components 是子地图自己

Menu地图加载了 Menu和Lobby的PDA

说明

每个地图放置BP_MapInfo蓝图

这含有3个PDALevel的primaryDataAsset主要数据资产

LevelKey、 MenuKey 、 LobbyKey

通过调用BP_GameInstanceMain对象的Get Current Level Class方法来判断关卡是否持有BP_MapInfo,

关卡中设置其LevelKey的数据资产:所在持久化的地图数据 + Map To Load的地图数据

BP_GameInstance_Main 主要实现SwitchLevel切换关卡管控

BP_GameMode_Main 配置选项

BP_PlayerController_Main 只让当前客户端判断Pawn类型并配置GameInstance所持有的InfoLevel对象为LevelKey,并让服务器生成VRPawn角色并更改持有,按键设置

和调用BP_PlayerState_Main设置PlayerIndex

BP_Helper_TransferPawn 初始化让服务器调用Controller生成Pawn的方法,获取BP_MapInfo的LevelKey传递给Controller

Map_Example_Persition根据Map_Info的PDA数据,打开Map_Intro地图 ,

Intro地图还有【BP_IntroScreen】即将加载Map_Menu

网络同步

GameInstance客户端和服务器端各一个,无网络复制功能

GameMode只有服务器端拥有1个

Controller服务器同玩家个数,客户端只有一个

Pawn和PlayState服务器和客户端都有,同玩家个数

渲染设置

自用打包exe

Render-Shader Permutation Reduction - Support Sky Atmosphere Fog √

Default Setting --ExtendDefault Luminance Range in auto exposure setting √

Substrate Materials √

Texture Streaming √

http://www.dtcms.com/a/450103.html

相关文章:

  • LabVIEW定时循环中止功能
  • 南昌中企动力做的网站怎么样宁波妇科
  • Async++ 源码分析10--ref_count.h
  • 单页面竞价网站网站+建设设计
  • 基于MATLAB的物理层算法原型验证
  • PHP网站开发程序员招聘一站式做网站哪家专业
  • 绵阳网站建设哪家好微信下拉小程序怎么关闭
  • 软件设计师——08 算法设计与分析
  • 炫酷企业网站网上买东西有哪些平台
  • DAY 42 Grad-CAM与Hook函数-2025.10.6
  • 绵阳网站建设培训学校隐私空间
  • 淮安网站建设做北京电梯招标的网站
  • 专业企业网站建设定制百度如何做网站
  • Net-Tools工具包详解:Linux网络管理经典工具集
  • 极路由做网站无锡网站推广公司排名
  • registrateAPI——非空函数
  • 环境设计案例网站基于html5动画的网站
  • CCF编程能力等级认证GESP—C++4级—20250927
  • 网站收录率怎样建立自己网站多少钱
  • 电商平台网站设计公司企业建站搭建
  • 【数据结构】链栈的基本操作
  • 实战分享:股票数据API接口在量化分析中的应用与体验
  • 个人建设网站还要备案么wordpress建站详细教程视频
  • Vue2 和 Vue3 View
  • 乐趣做网站厦门做网站的公司
  • 使用jmeter做压力测试
  • [工作流节点15] 推送消息节点在企业内部通知中的应用实践
  • 热转印 东莞网站建设ui界面设计英文
  • 【数据结构学习篇】--树
  • Linux中驱动程序通过fasync异步通知应用程序的实现