Physics Control
May 15, 2025About 10 min
Physics Control
物理控制组件允许您创建和管理多个控件,通常每个身体部位可以有多个控件。
分为两大类:
基础概念

Control
用于控制一个物理体相对于另一个物理体或者世界空间下,这些控制通过物理弹簧或者阻尼器驱动。这些控件可以在世界空间或父空间(类似于肌肉)中工作。每个控件都可以控制任意一对骨骼网格或静态网格(甚至是演员以外的网格)
创建

其中是Control Data
是FPhysicsControlData结构体,用来控制阻尼弹簧模型,其基本原理公式如下:
力 = 弹性系数 × (目标位置 - 当前位置) - 阻尼系数 × 当前速度
该结构体变量解释如下:
线性运动控制参数
参数 | 物理意义 | 典型值范围 | 效果说明 |
---|---|---|---|
LinearStrength | 弹簧弹性系数 (k) | ≥0 | 值越大,物体越"强硬"地趋向目标位置 |
LinearDampingRatio | 阻尼比 (ζ) | ≥0 | 1=临界阻尼,<1=欠阻尼(振荡),>1=过阻尼(缓慢) |
LinearExtraDamping | 额外阻尼系数 | ≥0 | 即使Strength=0也能提供阻尼效果 |
MaxForce | 最大施加力 | ≥0 | 限制弹簧能施加的最大力,防止剧烈运动 |
旋转运动控制参数
参数 | 物理意义 | 典型值范围 | 效果说明 |
---|---|---|---|
AngularStrength | 旋转弹性系数 | ≥0 | 控制旋转趋向目标角度的强度 |
AngularDampingRatio | 旋转阻尼比 | ≥0 | 类似线性阻尼但作用于旋转 |
AngularExtraDamping | 额外旋转阻尼 | ≥0 | 独立于AngularStrength的阻尼 |
MaxTorque | 最大扭矩 | ≥0 | 限制旋转控制的最大扭矩 |
目标速度处理
float LinearTargetVelocityMultiplier; // 线性目标速度乘数
float AngularTargetVelocityMultiplier; // 角度目标速度乘数
这些参数控制如何处理目标物体的速度:
- 1.0:完全跟随目标速度(适合角色动画)
- 0.0:忽略目标速度,仅基于位置控制(像普通弹簧)
- 中间值:部分跟随目标速度
骨骼动画集成
float SkeletalAnimationVelocityMultiplier; // 骨骼动画速度乘数
uint8 bUseSkeletalAnimation : 1; // 是否使用骨骼动画
这些参数实现了物理与动画的混合:
- 当
bUseSkeletalAnimation=true
时,物理系统会尝试匹配骨骼动画的运动 SkeletalAnimationVelocityMultiplier
控制动画影响的强度
控制点系统
FVector CustomControlPoint; // 自定义控制点位置
uint8 bUseCustomControlPoint : 1; // 是否使用自定义控制点
控制物理作用的"抓取点":
- 默认使用物体质心
- 可指定自定义偏移点(如抓取物体的边缘)
行为控制标志
标志 | 作用 | 使用场景 |
---|---|---|
bEnabled | 总开关 | 临时禁用控制而不删除 |
bDisableCollision | 禁用碰撞 | 连接体之间的无碰撞 |
bOnlyControlChildObject | 仅控制子物体 | 层级控制中的局部控制 |
常用的方法
方法 | 介绍 |
---|---|
bool SetControlData(...); | 完整数据设置 |
bool SetControlSparseData(...); | 部分数据更新 |
bool SetControlMultiplier(...); | 乘数设置 |
bool SetControlTarget(...); | 完整目标设置 FPhysicsControlTarget(位置,速度,方向,角速度) |
bool SetControlTargetPositionAndOrientation(...); | 位置+旋转 |
bool SetControlTargetPosition(...); | 仅位置 |
bool SetControlTargetOrientation(...); | 仅旋转 |
bool SetControlUseSkeletalAnimation(...); | 支持将动画目标与物理控制混合 |
Body Modifier
用于更新物理体的物理属性,比如使用模拟还是运行,或者它们是否有重力。躯体修改器用于修改物理躯体的模拟属性,例如调整重力效果,或在模拟运动和运动学运动之间切换。
创建

如果Set
没有设置,会自动加入All
集合。
FPhysicsControlModifierData
创建使用的参数是FPhysicsControlModifierData
名称 | 介绍 |
---|---|
MovementType (EPhysicsMovementType) | 定义物体应该如何移动 - Simulated:完全物理模拟 - Kinematic:运动学物体(不受力影响) - Static:静态物体 - 角色死亡时可能从 Kinematic 切换为 Simulated 实现布娃娃效果 - 拾取物品时可能从 Simulated 切换为 Kinematic |
CollisionType (ECollisionEnabled::Type) | 定义碰撞类型 - QueryOnly:仅用于射线检测等查询 - PhysicsOnly:仅用于物理碰撞 - QueryAndPhysics:两者兼具 - None:完全禁用碰撞 |
GravityMultiplier (float) | 模拟时的重力乘数 |
PhysicsBlendWeight (float) | 从模拟转换回动画时,模拟输出与原始动画输入的混合权重 - 平滑过渡:从0渐变到1实现自然的物理接管效果 - 部分控制:保持0.5实现动画与物理的混合 |
bUseSkeletalAnimation (bool) | 影响动画蓝图和物理模拟的更新顺序 - True:物理模拟在动画之后应用(如衣服模拟) - False:完全由物理驱动(如布娃娃) |
bUpdateKinematicFromSimulation (bool) | - 确保运动学物体与模拟物体保持同步 - 解决由于帧延迟导致的"撕裂"问题 - 如果为true,当关联的actor是运动学时,其变换将从模拟中更新 - 开启时会增加每帧的变换更新开销 - 但能避免视觉异常,特别是在高速移动时 |
常用方法
方法 | 介绍 |
---|---|
bool DestroyBodyModifier(...); | 销毁单个修改器 |
bool SetBodyModifierData(...); | 完整设置修改器数据 |
bool SetBodyModifierSparseData(...); | 稀疏数据更新(只更新设置过的字段) |
bool SetBodyModifierKinematicTarget(...); | 设置运动学目标变换 |
bool SetBodyModifierMovementType(...); | 设置运动类型(模拟/运动学/静态) |
bool SetBodyModifierCollisionType(...); | 设置碰撞类型 |
bool SetBodyModifierGravityMultiplier(...); | 设置重力乘数 |
bool SetBodyModifierPhysicsBlendWeight(...); | 设置物理混合权重(动画与模拟之间的混合) |
bool SetBodyModifierUseSkeletalAnimation(...); | 设置是否使用骨骼动画 |
bool SetBodyModifierUpdateKinematicFromSimulation(...); | 设置是否从模拟结果更新运动学 |
bool ResetBodyModifierToCachedBoneTransform(...); | 将身体重置为缓存的骨骼变换,谨慎使用每帧重置 |
World Space和Parent Space
Parent Space(父空间)
- 定义:以父骨骼或物体的局部坐标系为参考的空间。
- 特点:物理约束的计算基于父骨骼的局部坐标系,子物体的运动受父物体变换的影响。
- 示例:角色手臂的物理约束若设置为Parent Space,则手臂的旋转和位移会相对于肩部骨骼的局部坐标系计算。
World Space(世界空间)
- 定义:以游戏世界原点为参考的全局坐标系。
- 特点:物理约束的计算独立于父物体,直接基于世界坐标系。
- 示例:角色脊椎的物理约束若设置为World Space,则其位置和旋转会直接受世界坐标系控制,不受角色整体旋转的影响。
应用场景对比
场景 | Parent Space | World Space |
---|---|---|
关节控制 | 四肢运动(如手臂、腿部弯曲) | 脊椎或身体核心部位的全局定位 |
物理交互 | 角色行走时腿部关节的自然跟随 | 角色背靠座椅时脊椎的固定位置 |
参数调整 | 角强度(AngularStrength)为主 | 线性力(LinearStrength)和角强度结合 |
典型案例 | 角色奔跑时膝盖的弯曲 | 角色抓握方向盘时手部的全局定位 |
CreateControlsAndBodyModifiersFromLimbBones
常用于创建角色一系列物理控制和身体修改器,主要根据LimbSetupData
数据创建三种类型的物理控制元素:
- 世界空间控制(World-space controls)
- 父空间控制(Parent-space controls)
- 身体修改器(Body modifiers)
输出参数(引用传递)
- AllWorldSpaceControls:存储所有世界空间控制
- LimbWorldSpaceControls:按肢体分类存储世界空间控制(映射表,键为肢体名)
- AllParentSpaceControls:存储所有父空间控制
- LimbParentSpaceControls:按肢体分类存储父空间控制
- AllBodyModifiers:存储所有身体修改器
- LimbBodyModifiers:按肢体分类存储身体修改器
输入参数
- SkeletalMeshComponent:目标骨骼网格组件,将对其施加物理控制
- LimbSetupData:肢体设置数据数组,定义如何创建各个肢体的控制
- WorldSpaceControlData:世界空间控制的默认参数
- ParentSpaceControlData:父空间控制的默认参数
- BodyModifierData:身体修改器的默认参数
- WorldComponent:(可选)指定"世界"对象的网格组件,使世界控制可以在另一个对象空间中工作
- WorldBoneName:(可选)如果WorldComponent是骨骼网格,可以指定特定的骨骼名
FPhysicsControlLimbSetupData
名称 | 介绍 |
---|---|
LimbName | 要创建的肢体名称 |
StartBone | - 通常是肢体中最靠近根部的骨骼 - 例如定义左臂时可能是左锁骨(left clavicle) - 肢体将包含此骨骼及其子骨骼 |
bIncludeParentBone | - 是否包含起始骨骼的父骨骼 - 用于像脊柱这样的肢体,你可能想包含骨盆(脊柱的父骨骼) |
bCreateWorldSpaceControls | 是否为该肢体创建世界空间控制 |
bCreateParentSpaceControls | 是否为该肢体创建父空间控制 |
bCreateBodyModifiers | 是否为该肢体创建身体修改器 |
创建核心逻辑
控制元素的创建:
- 为每个肢体创建三种控制元素(根据LimbSetupData中的标志决定是否创建)
- 使用传入的ControlData和ModifierData作为默认参数
分类存储机制,每个创建的控制元素会被添加到三个集合中:
- "All"集合(包含所有该类型的控制)
- "ControlType"集合(如"WorldSpace"或"ParentSpace")
- "ControlType_LimbName"集合(如"WorldSpace_ArmLeft")
每个身体修改器会被添加到:
- "All"集合
- "LimbName"集合(如"Spine"或"LegRight")
世界空间控制的可定制性:
- 通过WorldComponent参数,可以指定世界控制基于另一个对象的空间
- 如果WorldComponent是骨骼网格,还可以指定特定的骨骼(WorldBoneName)
使用例子
物理方块

创建步骤:
- 创建一个空的
Actor
并添加Cube
! - 开启
Cube
的物理模拟并关闭重力 - 添加
PhysicalControl
组件,值得注意的是该组件应该放在Cube下面,不然会出现控制不了的问题 - 创建一个控制器,使
Cube
一直在Actor
的位置 Control Data
的LinearStrength
需要设置一下,初始化出来是0
受击反馈

设置约束描述文件:

如何锁住脚?
需要把骨骼网格的Physics Transform Update Mode 设置为 Component Transform is Kinematic
单杠
控制骨骼蒙皮
角色物理动画
// 设置一个柔软的身体物理控制
ControlData.LinearStrength = 100.0f;
ControlData.LinearDampingRatio = 0.8f; // 轻微弹性
ControlData.bUseSkeletalAnimation = true;
ControlData.SkeletalAnimationVelocityMultiplier = 0.7f;
物理抓取系统
// 设置一个稳定的物体抓取控制
ControlData.LinearStrength = 500.0f;
ControlData.LinearDampingRatio = 1.2f; // 过阻尼避免振动
ControlData.MaxForce = 2000.0f;
ControlData.bUseCustomControlPoint = true;
ControlData.CustomControlPoint = GrabLocationOffset;
布娃娃局部控制
// 仅控制上半身物理
ControlData.AngularStrength = 50.0f;
ControlData.AngularDampingRatio = 1.0f;
ControlData.bOnlyControlChildObject = true;
ControlData.bDisableCollision = true;
布娃娃系统
// 创建全身修改器
TArray<FName> Modifiers = PhysicsControlComp->CreateBodyModifiersFromSkeletalMeshBelow(
SkeletalMeshComp,
TEXT("root"),
true,
TEXT("All"),
FPhysicsControlModifierData(
EPhysicsMovementType::Simulated,
ECollisionEnabled::QueryAndPhysics,
1.0f, // Gravity
1.0f, // Physics blend
false, // bUseSkeletalAnimation
true // bUpdateKinematicFromSimulation
));
// 禁用动画影响
PhysicsControlComp->SetBodyModifiersUseSkeletalAnimation(Modifiers, false);
物理抓取物体
// 设为运动学并保持碰撞
ModifierData.MovementType = EPhysicsMovementType::Kinematic;
ModifierData.CollisionType = ECollisionEnabled::QueryAndPhysics;
ModifierData.GravityMultiplier = 0.0f; // 抓取时忽略重力
动画-物理混合
// 50%混合动画和物理
ModifierData.PhysicsBlendWeight = 0.5f;
ModifierData.bUseSkeletalAnimation = true;