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
来生成
BP_MapInfo
放置在场景中的具体对象,主要就是为了配置Info_Level
,在BP_GameInstance_Main
类中直接通过方法GetCurrentLevelClass
从此对象去要到Info_Level
Info_Level
Streaming Level
用于加载子关卡,比如当前关卡是TestMainMap,LevelsToLoad设置为TestMap01,那么在进入TestMainMap后会自动加载TestMap01
Transition
切换关卡的选项,首先设置时间变量,如果是0就是瞬间加载,可以设置天空球贴图和背景色
Panel
关卡面板的UI布局信息,可以参考demo演示的布局,见下图
key
本地化文字有关的一个变量,此框架是用表格的方式设置本地化。
此变量作为DataTable的RowName读取表格
pawn
对应平台的pawn设置
Pallet
LevelImage变量决定关卡在Map面板下的显示图片,如下图
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/传送
- 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/移动
- 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
:对应按键映射中的TurnLeft
和TurnRight
的转向角度
按键映射补充
- Trigger Grip:是否允许长按select的按钮来触发grip(默认是0.4秒,可以通过BP_MCmop_Laser中的Handle Trigger来修改长按间隔)
- Holding Grip:是否允许按下按钮抓取,松开按钮放开,或者为单次按下抓取,抓取状态下再次按下松开
关于按键的自定义
按键的起始点在Pawn内,如下截图
调用到BP_MotionController
内的方法KeyInput
,然后遍历调用所有BP_MComp
组件的方法FunctionInput
,然后继承自BP_MComp
的组件各自实现/重写按键对应的逻辑,一般可以用一个Switch来做
如需要添加自定义按键事件,修改枚举Enum_Control_Function
即可
Comp_RadialMenu
如图所示,框架默认给予2个RadialMenu事件,分别可以设置2个面板,
Comp_UI_Display
如图所示,手部内测的面板,通过设置该组件配置
Comp_UI_Pallet
一个次级面板,在RadiaMenu面板中如果指定了对应的类就可以触发此面板,比如指定了BP_Radial_Button_Pallet_Bookmarks
,在此组件内就可以配置相应的Bookmarks内容
此组件又非常多的功能,之后逐步细讲
DataAssets
首先要回顾一下Info_Level
类中有一个ActorInfos
列表,需要在里面添加所有需要用到的表
如上图所示,我们需要的DA_Test资源需要从PDA_ActorList
创建,此类是继承自PrimaryDataAsset
的蓝图类,内部就是创建了一系列变量;然后把这个资源放入Info_Level
内
然后我们右键自建蓝图类,CreateDatatableEntry
,主要选择标签和ActorList
,创建后自动生成基础的DataAsset,即可添加到之前创建的DA_Test
内
然后我们以Map_Demo_UI
关卡做测试,找到类BP_Pallet_ObjectDropper
的Comp_UI_Pallet
组件,配置如下
运行以后就得到如下结果
Comp_Select
关于选择的组件,比较基础也比较有用
对于VR玩家,默认使用Trigger
按键类出发select功能
- 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变量为上次的反向值
- SnapType:吸附规则
- SectionSet:分段极值设定
- TriggerAlsoOwner:通知owner
- ComponentTagToSearch:需要拖动的mesh需要加上该标签
使用流程
在被拖动的模型中加入插槽
AttachPoint
来指定交互点确保交互模型可以被射线检测到
挂上
Comp_Drag
,然后需要配合Comp_Latch
使用,该组件可以使用默认值在交互模型中加入以上2个组件所需要的tag,默认为
Drag,Latch
可以配合
Comp_ListenToServer
使用,可以监听每次到达极值的时间,或者Tick的Drag事件同一个类下可以挂载多个Drag组件来拖动不同的模型组件,记得修改
identifier
和ComponentTagToSearch
,也需要修改Latch组件的ComponentTagToSearch
变量,也不要忘记区分不同模型的Tag如果是spline模式,在类内创建一个spline组件
Comp_Grab
抓取组件,对于VR玩家可以有射线和接触抓取两种方式,不过具体的功能会有区别,见下图
变量解释
- GrabType:是否在抓取后模拟物理,利用的是
PhysicsHandle
的抓取机制,一般的需要把模型放到root位置 - SnappingType:取消抓取后吸附的过程是否开启物理模拟
- ShouldKeepUpright:在抓取后是否保持世界坐标正前方
- ShouldAutoPickup:VR模式下手部接触以后直接抓取
- CanBePickedUp:是否可以被抓取
- SnapAndReplaceControlls:抓取之后替换手柄预设的所有操作,直到release为止,之后手柄的操作可以映射到组件的
KeyInput
和Thumbsticks
方法中 - 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
- Anchor_Deactived:关闭吸附效果
- Allow_Physics:吸附后启用物理
- Connect_IDs_To_Allow:需要与配套组件对应的ID
- Connect_Should_Attach:子物体吸附到此物体后是否attach
- Sphere_Radius:查找半径
- Attached_Lock:吸附以后锁定,即不能再交互
Comp_Connect_Anchor
- 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:判断连接时的球形射线距离组件原点的距离
最终效果
Comp_Latch
在之前Grab组件中已经有用到,主要作用是用来锁定位置
主要设置就是LatchType
- Drag:对应的是就是抓取
- SimpleLatch:简单的吸附,不需要配合Grab组件,手靠近以后就自动吸附,针对VR玩家
- Climb:攀爬模式,可以用于攀岩类操作,针对VR玩家
Comp_ListenToServer
除了上面的Grab用到的功能,该组件还有其他作用
Light
设置为Light
模式,需要配合组件Comp_Light
使用,在类内需要至少给一个光源,对于多个光源可以一起被作用
测试类如下图
如果使用
ListenToSingle
模式那么对于Drag过来的事件按50%作为临界点开关
Active
详情请看后面的Comp_Active
Open
详情请看后面的Comp_Open
Window
详情请看后面的Comp_WindowObject
Comp_Active
配合其他可以发送active事件的组件使用,如select.
该组件可以收到事件ActiveStateChanged
和ConstActiveStateChanged
,自行实现后续的逻辑
Comp_Open
配合其他可以发送Open事件的组件,比如Select或者Drag组件,来实现移动、旋转或者缩放的操作
需要将key的值对应到交互模型的tag
可以通过Listen组件来监听其他类的事件发送
Comp_Overlap
一般搭配Drag组件来模拟按钮效果
如上图所示,绿色模型开启overlap效果,增加tag成员overlap
,drag
抓取其他物件对绿色部分overlap以后就能模拟按钮效果
Comp_WindowObject
主要是文字和图片说明的窗口,可以配合Select组件展示
需要注意的是挂载此组件的类必须注册到PDA_Actor_List
里面,否则框架没有判空直接报错,具体请看之前Info_level
以及Data_Assets
内容
Comp_Visual
改变外观的组件,一般配合select组件的selectionMenu
模式,然后在SelectionTypes
内添加VisualChange
成员来实现
- CurrentMaterials:当前的材质类型,对应下面的配置
- PossibleMaterials:材质配置表
- Key:材质效果的键
- ButtonMaterial/ButtonTexture:按钮的材质和图片
- MeshInfo:替换模型的效果
- Key:需要把这个值填写到模型的Tag中去
- Value:替换模型的模型和材质效果
Comp_Widget
封装了UMG的组件,同时方便于交互
- 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可以用来覆盖原有材质,让物体在小地图里显示特殊材质
然后需要若干个地面,用框架中的类BP_Floorplanmeasurement
指定贴图,该贴图最好跟场景的样貌匹配,给定FloorName,用于显示在面板上的名称
2DMap
使用类BP_2DMap
,直接拖入场景中即可,记得设置InitTab
3DMap
使用类BP_3DMap
,拖入场景中以后需要给与变量Measurement
一个地面单位即可显示3D地形;
或者直接使用Comp_Child_3DMap
也是一样的,记得把地形的缩放拷贝到这个类的缩放中,不然会导致变形