UE4实现VRInteractableActor与镭射配件
VRInteractableActor
首先,继承ZomboyInteractableActor蓝图
Mesh
通常将Scene或者Mesh作为RootComponent
StaticMesh: Mesh: Primitive: SceneComp,为什么Mesh能有Physics和Collision的功能?
Mesh里提供了OverrideMaterials的配置(TArray),但它还不能直接拿来用,它只是各种Mesh组件的抽象基类。而StaticMeshComp里缓存了UStaticMesh的引用,因此它可以对其进行操作
InteractionComponent
配置触发交互的范围(ZomboyShapeComponent)
配置GripType:Follow(手跟随物)或Grab(物跟随手)
配置MaxConcurrent: 可以几只手交互
InteractionDetectionDistance
手离开交互范围,会自动结束Interaction
GeneralIndicator
Transfrom尽量不要修改,因为它会控制整体,可能会造成意想不到的效果
表示交互时手的位置,该位置应与控制器握持位置接近,且和触发交互的范围相近
配置手各个拇指的位置 HandPose
配置控制器位置 ControllerRelative(点控制器出现的圆球是整体的变换点,注意!控制器没有变换点)应放在你想让手柄放的位置
配置手的位置 HandRelative (手的控制点在手掌根部那个点) 应放在你想表现的预期位置
需要注意的是,这两个都是RelativeTransform,它会相对Indicator结点的Transform进行变化
配置左手还是右手交互 HandUsage
实现抓取移动
比如上下移动
原理:在OnPreGripUpdateEvent事件里 GetDesiredHandPoseTransformWorldSpace(控制器位置)- GetTargetHandPoseTransformWorldSpace(手部模型当前位置)= 控制器输入的偏移值
上下移动就是取Z分量的值,如果要限制一帧移动的范围,就再Clamp一下VectorSize。得到的向量作为Actor的LocalOffset

更进一步,由于只是ClampVectorSize无法限定交互物移动的范围,所以我们还要对交互物最终的Location进行一下Clamp:

SetHandPoseTransformWorldSpce设置手最终的位置,SetRelativePosition设置交互物自身的位置
怎么实现左手交互
从右手复制,设置HandUsage为Left,然后Visualization里面设置 MotionSourceIsRightHand False,这决定是预览左手还是右手动作。设置右手时,时常看一下左手的效果,这样才不会错
把交互物加到主角身上
用ChildActor或AttachActorToComponent
LaserAttachment
属性:Enable 开关功能
EventBeginPlay: SetTickEnabled False, SetTickGroup: PostPhysics
OnAttachmentInstallation: 开启Enable和SetTickEnabled,计算旋转,开启激光可视
OnAttachmentPulled: 上述操作的反向
EventTick: 由LaserBeam起始点到ValidInstance终点进行LineTraceByChannel检测,实时缩放LaserBeam和显隐LaserGlow
Tick
补充:
- PrePhysics:默认。它使用的是上一帧的物理数据,通常用于实现Actor和物理对象的交互,随后计算物理模拟
- DuringPhysics:和物理模拟同时。通常用于与物理无关的而又落后于PrePhysics逻辑的操作,如更新小地图
- PostPhysics:在物理位置更新之后。常用于追踪(如激光瞄准器,它必须从枪的最终位置发出,即使出现一帧延迟也很明显),这时所有物理对象将位于它们的最终位置
- n/a:处理隐藏操作、tick 世界时间管理器、更新摄像机、更新关卡流送体积域和流送操作。
- PostUpdateWork 相机更新之后,通常用于依赖相机的特效。也可用于在帧中绝对最靠后运行的游戏逻辑
- n/a:创建Defer Actor和渲染

- Tick初始是否Enable
- Tick时间间隔
- Paused时是否Tick
- DS上运行时是否Tick
- Tick Group
UE中SetLocation是立即执行的,没有同一帧中位移多次合并为一个的优化
Merge后手部抓取、镭射功能失效等奇奇怪怪的问题
可能是继承坏了,重新拉个蓝图实现试一下
CS_Character
全身IK和手部IK同时存在,HandOnly时是隐藏全身的模型
Anomotion BIK是一个全身IK插件。VR要做到全身IK还需要捕捉设备支持
如这里要实现InteractableActor的最终手部模型的Z轴是TargetPose的Z,而Y轴(手朝向的地方)是DesiredPose的Y,那么MakeRotFromZY(首先保Z不变,一定朝上),最后赋给SetPose(实现手抓滑动杆时手腕可旋转的效果)
例:ClimbPipe
它是用ClimbComponent实现PhysClimb的移动模式,交互上它FindTransformClosestToWorldLocation
例:Door
逻辑事件:OnPreGripUpdateEvent(前后推Interaction)→SetHandPoseTransformWorldSpace→SetWorldRotationOnPreGripUpdateEvent(DoorNob门把手)→GetDesiredHandPoseTransformWorldSpace→SetTargetLocation(Target是PhysicsHandle2)OnHandInteractionBegin/EndEvent→Add/Destroy PhysicsHandleComponent→Set DoorNobPhysicsHandle2→GrabComponent AtLocation(Door→Desired HandPose Transform Location)