VR框架AdvancedVRFrameworkV3_1分析

虚幻商城有一个非常成熟而且有诚意的VR框架,涵盖了基本上VR可以用到的所有主流功能,同时也有PC和移动端的支持。

商城链接

趁着项目需求借机分析一下这个框架,后续打算基于此扩展适用于项目的框架

分析记录

2020.8.21:

1.纯蓝图+组件的思路搭建,使用起来不算麻烦也不能算太方便,学习成本还是有的

2.解耦做的不是特别的好,很多类之间有强依赖,少一个就报错

3.功能做的非常完善,该有的基本的有了

4.性能无实测,但是各类组件无脑Tick初步看有性能压力

5.部分内容比如地图、边缘发光、武器/弓箭交互等单独拎出来都是非常实用的功能

关卡管理

必要元素
  • GameMode
  • BP_Info_Map
  • BP_Info_Level
  • BP_PostProcess
  • BP_PlayerPostion

以上的这些都可以用EU_Widget来生成

image-20200820111916928

BP_MapInfo

放置在场景中的具体对象,主要就是为了配置Info_Level,在BP_GameInstance_Main类中直接通过方法GetCurrentLevelClass从此对象去要到Info_Level

Info_Level
Streaming Level

用于加载子关卡,比如当前关卡是TestMainMap,LevelsToLoad设置为TestMap01,那么在进入TestMainMap后会自动加载TestMap01

Transition

切换关卡的选项,首先设置时间变量,如果是0就是瞬间加载,可以设置天空球贴图和背景色

Panel

关卡面板的UI布局信息,可以参考demo演示的布局,见下图

image-20200820135730829

key

本地化文字有关的一个变量,此框架是用表格的方式设置本地化。

此变量作为DataTable的RowName读取表格

pawn

对应平台的pawn设置

Pallet

LevelImage变量决定关卡在Map面板下的显示图片,如下图

image-20200820140512683

BP_PostProcess

维护后期效果的类,主要目的是用于高光显示,当然高光显示还有其他几个方式,只是后期方式效果比较好

BP_PlayerPostion

玩家起始位置,内部主要实现了一个传送玩家并校准位置的方法

VR玩家配置

VR玩家需要继承自BP_Pawn_VR或者BP_Pawn_VR_Char,区别在于后者提供了一个半身小白人模型

Comp_Controller_VR
  • Controller Set

自定义对应MotionController的类,框架给的BP_MotionController_Hands内通过4个ChildrenActor分别实现模型、传送、菜单、移动功能,具体功能类如下

  • BP_MComp_Teleport:传送功能,以及传送效果的一些参数配置
  • BP_MComp_Hand:手模型以及动画,提供一些抓取等参数的设置
  • BP_MComp_Controller:控制器模型,代替手
  • BP_MComp_RadialMenu:菜单功能
  • BP_MComp_Movement:移动功能
  • BP_MComp_Trigger:单纯用于监听按键事件的组件,可以用来扩展输入事件
  • BP_MComp_Laser:射线功能组件,提供一些射线相关参数配置
  • BP_MComp_Smartwatch:手表菜单组件,需要配置相应UMG

如果设置了Controller Mesh Override,就会用相应的模型覆盖上面设置的模型

  • ControlsPresets

对应平台的按键映射

  • Haptics
    • HapticsForSelect:在点开Select选单时手柄震动
    • HapticsForDevices:在与工具类型的道具交互时手柄震动
    • HapticsForGrab:在触发Grab时手柄震动
    • HapticsForTrigger:在各种操作触发触发器需要修改set值时手柄震动
Teleport/传送
  • image-20200820142920984
  • Teleport Mode:配置不同的传送交互类型
    • TeleportFree:传送到射线所指定的位置,但是在Z轴normal值小于30度的情况下不允许传送
    • TeleportAreaSelect:激活Teleport出现网格,触发手柄上的select操作进行传送,传送后网格消失
    • TeleportAreaActive:手柄指向地面时出现网格,激活Teleport即传送
    • Nav Mesh:在寻路网格可达的范围内进行传送,交互与TeleportFree类似,但是取消了30度的角度判断
  • Teleport Search Type:用于传送的射线类型
    • Straight:直线射线指向
    • Projectile:抛物线射线指向
  • Teleport Time:传送所花费的总时间
  • Use Teleport Motion:设定传送的过渡类型
    • None:没有过渡态,直接传送到目标点
    • Indication:location具有过渡态,逐步过渡到目标点
    • FullMotion:location与rotation都具有过渡态,位置过渡到目标点且角色的rotation过渡到目标rotation

在配置按键映射的DataAssets内相关的teleport选项

  • Teleport Execute:传送触发的条件
    • OnTrigger:trigger按键按到底触发
    • OnThumbstickRelease:thumbstick按下并松开时(通过thumbstick来转向时比较好用)
    • OnTeleportButtonRelease:上面注册的Teleport按钮被按下并松开时
  • Teleport Deactivate:传送取消的条件
    • OnlyExecute:只允许被触发不允许取消
    • NeutralThumbstick:trackpad中键取消传送
  • TeleportRotationType:传送时的面向操控
    • None:无法转向
    • RotateByThumbstick:通过trackpad来操作传送时的方向
    • RotateByHand:通过手的转向来操作传送时的方向
Movement/移动

image-20200820143452130

  • Movement Style:移动的方式
    • Fluent:在地面上以固定速度移动
    • StopMotion:当walk的按钮按下后产生一个ghost,然后移动固定秒后瞬移到ghost的位置,若提前松开则取消移动,最多两秒
    • Ghost:当walk的按钮按下后产生一个ghost,松开则瞬移到ghost的位置
  • Ghost Behaviour:Ghost的位移操作形式配置
    • Direction:通过手柄的方向来操作ghost移动的方向与速度
    • MovementRelativeToOrigin:通过按下walk按钮时的初始位置来计算后续的相对偏移量来操作ghost的移动,非常难用
    • PositionRelativeToOrigin:按下按钮后通过手柄的移动距离来移动ghost的位置,通过手柄的方向来改变ghost的朝向
  • Stop Motion Interval:用于配置StopMotion的固定秒数时间,大于2秒也会被设置成2秒
  • Movement Speed:ghost移动的速度
  • Move with Fade:瞬移时是否允许黑屏过渡
Rotation

RotateDerees:对应按键映射中的TurnLeftTurnRight的转向角度

按键映射补充
  • Trigger Grip:是否允许长按select的按钮来触发grip(默认是0.4秒,可以通过BP_MCmop_Laser中的Handle Trigger来修改长按间隔)
  • Holding Grip:是否允许按下按钮抓取,松开按钮放开,或者为单次按下抓取,抓取状态下再次按下松开
关于按键的自定义

按键的起始点在Pawn内,如下截图

image-20200820145557962

调用到BP_MotionController内的方法KeyInput,然后遍历调用所有BP_MComp组件的方法FunctionInput,然后继承自BP_MComp的组件各自实现/重写按键对应的逻辑,一般可以用一个Switch来做

如需要添加自定义按键事件,修改枚举Enum_Control_Function即可

Comp_RadialMenu

image-20200820150244981

如图所示,框架默认给予2个RadialMenu事件,分别可以设置2个面板,

image-20200820150349447

Comp_UI_Display

image-20200820150423064

image-20200820150455057

如图所示,手部内测的面板,通过设置该组件配置

Comp_UI_Pallet

一个次级面板,在RadiaMenu面板中如果指定了对应的类就可以触发此面板,比如指定了BP_Radial_Button_Pallet_Bookmarks,在此组件内就可以配置相应的Bookmarks内容

此组件又非常多的功能,之后逐步细讲

DataAssets

首先要回顾一下Info_Level类中有一个ActorInfos列表,需要在里面添加所有需要用到的表

image-20200820164521985

如上图所示,我们需要的DA_Test资源需要从PDA_ActorList创建,此类是继承自PrimaryDataAsset的蓝图类,内部就是创建了一系列变量;然后把这个资源放入Info_Level

image-20200820165040854

然后我们右键自建蓝图类,CreateDatatableEntry,主要选择标签和ActorList,创建后自动生成基础的DataAsset,即可添加到之前创建的DA_Test

然后我们以Map_Demo_UI关卡做测试,找到类BP_Pallet_ObjectDropperComp_UI_Pallet组件,配置如下

image-20200820165341595

运行以后就得到如下结果

image-20200820165410975

Comp_Select

关于选择的组件,比较基础也比较有用

对于VR玩家,默认使用Trigger按键类出发select功能

image-20200820172012396

  • SelectMenu

对应上面的变量SelctionTypes,点击以后就自动生成按钮

  • Custom

自定义PressSelect事件就可以

  • Trigger

需要配合组件Comp_ListenToTrigger 使用,点击以后Comp_ListenToTrigger::TriggerSingle能执行

可以设置ActorsToTrigger变量来让其他类收到Listen消息

设置ComponentTagToSearch可以对类内的不同模型进行筛选

  • window

详情请看后面的Comp_WindowObject

  • visual

配置请看后面的Comp_Visual,区别于SelectMenu+VisualChange的组合,如果直接指定Visual则是直接切换,无菜单提示

  • light

配合光源和Light组件一起使用

  • open

详情请看后面的Comp_Open

  • active

详情请看后面的Comp_Active

Comp_Drag

拖拽组件,可以平移和旋转拖拽,一般需要配合Latch组件来使用

变量解释
  • identifier:组件之间交互的名称,如果类内有多个Drag组件就需要区分不同的名称
    DragType:拖动规则
    • key:具体规则,如变量名称描述的含义
    • value
      • SnapType:吸附规则
        • FreeMovement:自由移动
        • SnapToSegment:吸附到最近的分段,即下面的sectionSet分段
        • Reset:重置为初始状态
      • StartPositon:初始位置
      • SnappingSpeed:吸附速度
      • FollowSpeed:跟随速度
      • SelectRule:取值方式,3个选项以此为四舍五入,ceil,floor
      • Toggle:强制设定每次到达极值时的set变量为上次的反向值
  • SectionSet:分段极值设定
  • TriggerAlsoOwner:通知owner
  • ComponentTagToSearch:需要拖动的mesh需要加上该标签
使用流程
  • 在被拖动的模型中加入插槽AttachPoint来指定交互点

  • 确保交互模型可以被射线检测到

  • 挂上Comp_Drag,然后需要配合Comp_Latch使用,该组件可以使用默认值

  • 在交互模型中加入以上2个组件所需要的tag,默认为Drag,Latch

  • 可以配合Comp_ListenToServer使用,可以监听每次到达极值的时间,或者Tick的Drag事件

  • 同一个类下可以挂载多个Drag组件来拖动不同的模型组件,记得修改identifierComponentTagToSearch,也需要修改Latch组件的ComponentTagToSearch变量,也不要忘记区分不同模型的Tag

  • 如果是spline模式,在类内创建一个spline组件


Comp_Grab

抓取组件,对于VR玩家可以有射线和接触抓取两种方式,不过具体的功能会有区别,见下图

image-20200821095808183

变量解释
  • GrabType:是否在抓取后模拟物理,利用的是PhysicsHandle的抓取机制,一般的需要把模型放到root位置
  • SnappingType:取消抓取后吸附的过程是否开启物理模拟
  • ShouldKeepUpright:在抓取后是否保持世界坐标正前方
  • ShouldAutoPickup:VR模式下手部接触以后直接抓取
  • CanBePickedUp:是否可以被抓取
  • SnapAndReplaceControlls:抓取之后替换手柄预设的所有操作,直到release为止,之后手柄的操作可以映射到组件的KeyInputThumbsticks方法中
  • RelativeControllerPostion:抓取以后的相对位置校准
  • MaxDistanceToSocket:最大抓取距离(距离socket)
  • SpawnTinyDisplay:抓取以后生成小提示面板,需要用DA去配置,同样的只支持VR射线模式
  • GrabAttachedActorInstead:决定是否抓取此物体时替换掉之前抓取的物体
  • GrabTag:默认抓取类中的所有物体,可以用此标签区分

Comp_Connector_Surface

配合Grab组件一起使用,目的是

  • RotateOnSurface:决定如何旋转,是否垂直墙面等
  • ShouldBeActiveEvenIfPhysics:如果开启物理模拟,就需要开启此选项,防止过多碰撞挤压
  • AllowPhysicsAfterSnap:此物体吸附到平面后是否启用物理模拟
  • RequiresTag:对吸附的平面做tag判断
  • SearchDistance:吸附距离

需要特别注意的是,需要设置此组件的朝向问题,默认是X轴检测

Comp_Anchor/Comp_Connect_Anchor

特殊的吸附配套组件,后者吸附到前者

Comp_Anchor

image-20200821170439723

  • Anchor_Deactived:关闭吸附效果
  • Allow_Physics:吸附后启用物理
  • Connect_IDs_To_Allow:需要与配套组件对应的ID
  • Connect_Should_Attach:子物体吸附到此物体后是否attach
  • Sphere_Radius:查找半径
  • Attached_Lock:吸附以后锁定,即不能再交互
Comp_Connect_Anchor

image-20200821170830375

  • Tag Of Component to Attach:初始时此Actor attach到Attached to Actor下的带有此tag的component中
  • Attached to Socket:当Attached to Actor不为None,且Tag Of Component to Attach也不为None时,该actor会attach到Tag Of Component to Attach所提到的component中的名为Attached to Socket的socket中,若Attached to Actor不为None,但是Tag Of Component to Attach为None时,此Actor会attach根组件下名为Attached to Socket的socket上,若没有则会attach到Attached to Actor的根组件下
  • ConnectorID:与配套组件对应的ID
  • SearchRadius: 查找半径
  • SearchDistance:判断连接时的球形射线距离组件原点的距离

最终效果

image-20200821171243617

image-20200821171309985

Comp_Latch

在之前Grab组件中已经有用到,主要作用是用来锁定位置

主要设置就是LatchType

  • Drag:对应的是就是抓取
  • SimpleLatch:简单的吸附,不需要配合Grab组件,手靠近以后就自动吸附,针对VR玩家
  • Climb:攀爬模式,可以用于攀岩类操作,针对VR玩家

Comp_ListenToServer

除了上面的Grab用到的功能,该组件还有其他作用

Light

设置为Light模式,需要配合组件Comp_Light使用,在类内需要至少给一个光源,对于多个光源可以一起被作用

测试类如下图

image-20200821105432348

如果使用ListenToSingle模式那么对于Drag过来的事件按50%作为临界点开关

Active

详情请看后面的Comp_Active

Open

详情请看后面的Comp_Open

Window

详情请看后面的Comp_WindowObject

Comp_Active

配合其他可以发送active事件的组件使用,如select.

该组件可以收到事件ActiveStateChangedConstActiveStateChanged,自行实现后续的逻辑

Comp_Open

配合其他可以发送Open事件的组件,比如Select或者Drag组件,来实现移动、旋转或者缩放的操作

需要将key的值对应到交互模型的tag

可以通过Listen组件来监听其他类的事件发送

Comp_Overlap

一般搭配Drag组件来模拟按钮效果

image-20200821152007053

image-20200821152143566

如上图所示,绿色模型开启overlap效果,增加tag成员overlap,drag

抓取其他物件对绿色部分overlap以后就能模拟按钮效果

Comp_WindowObject

主要是文字和图片说明的窗口,可以配合Select组件展示

需要注意的是挂载此组件的类必须注册到PDA_Actor_List里面,否则框架没有判空直接报错,具体请看之前Info_level以及Data_Assets内容

image-20200821172837931

image-20200821172859847

Comp_Visual

改变外观的组件,一般配合select组件的selectionMenu模式,然后在SelectionTypes内添加VisualChange成员来实现

image-20200821154014085

  • CurrentMaterials:当前的材质类型,对应下面的配置
  • PossibleMaterials:材质配置表
    • Key:材质效果的键
    • ButtonMaterial/ButtonTexture:按钮的材质和图片
    • MeshInfo:替换模型的效果
      • Key:需要把这个值填写到模型的Tag中去
      • Value:替换模型的模型和材质效果

image-20200821154329493

Comp_Widget

封装了UMG的组件,同时方便于交互

image-20200821160827586

  • UsesRecursiveWidgetSelection:使用框架自定义的UMG交互,如Widget_Button
  • ‘UsesWidgetInteractionComponent:使用默认UMG空间交互,如Button
UsesRecursiveWidgetSelection

我们创建一个继承自Widget_Pallet_Button_Normal的UMG,直接放入测试UMG中,监听Pressed事件即可得到点击事件

UsesWidgetInteractionComponent

创建一个Button,点击交互后就可以走到Pressed事件

要注意Clicked事件无效

框架UMG类

待补充….


Map

小地图的使用,分为2D和3D两种模式

在需要显示在地图上的类中需要挂载组件Comp_MapLocation

设置Icon及尺寸,以及是否支持旋转缩放等选项

SubstitueMaterial可以用来覆盖原有材质,让物体在小地图里显示特殊材质

image-20200821112246681

然后需要若干个地面,用框架中的类BP_Floorplanmeasurement

指定贴图,该贴图最好跟场景的样貌匹配,给定FloorName,用于显示在面板上的名称

2DMap

使用类BP_2DMap,直接拖入场景中即可,记得设置InitTab

3DMap

使用类BP_3DMap,拖入场景中以后需要给与变量Measurement一个地面单位即可显示3D地形;

或者直接使用Comp_Child_3DMap也是一样的,记得把地形的缩放拷贝到这个类的缩放中,不然会导致变形