Active Ragdoll:从动画角色到物理角色
从动画与物理的根本矛盾出发,理解 Active Ragdoll 如何借助刚体、关节与反馈控制构造真正存在于物理世界中的角色,并系统讨论 PD Controller、平衡、行走、受击、抓取、Get Up 与 Unity 实现中的稳定性问题。
普通动画角色可以精确地奔跑、挥拳、攀爬和装弹,却往往并不真正“存在”于物理世界中。
手臂撞到墙,动画仍然希望它继续向前;一辆汽车撞上正在奔跑的 NPC,Animator 仍然可以若无其事地播放 Run;玩家抓住角色的手腕,角色骨骼与玩家施加的力之间也未必存在真正的动力学关系。
传统 Ragdoll 恰好走向另一个极端。
它拥有质量、惯性、碰撞和关节,能够自然地跌落、滚动和被击飞,却失去了主动行动的能力。它会遵守物理,却不会自己站立,更不会挥拳、奔跑和保持平衡。
Active Ragdoll(主动布娃娃)试图连接这两个世界。
它的核心思想不是“在动画和 Ragdoll 之间切换”,而是:
让一个真正参与物理模拟的身体,主动尝试完成动画或程序所表达的动作。
动画不再直接决定身体最终在哪里,而只是描述:
“我想成为这个姿势。”
身体通过关节产生类似肌肉的力矩去追逐目标姿态;与此同时,碰撞、重力、惯性、摩擦和外力仍然由物理解算器共同处理。
于是角色可以一边试图站立,一边真的被箱子推倒;一边尝试挥拳,一边因为手撞到墙而被迫弯曲手臂;一边努力奔跑,一边因为失去支撑而跌倒。
这使 Active Ragdoll 不只是一个动画技巧。
继续深入以后,它会把:
- Skeleton Animation
- Rigidbody
- Joint
- Constraint Solver
- PD Controller
- IK
- Balance
- Locomotion
- Procedural Animation
甚至机器人控制中的一些基本思想连接到同一个问题上:
如何控制一个受到物理规律约束的身体?
本文以下 Unity API 以 Unity 6.0 的内置 3D Physics 文档为基准。Unity 的 GameObject 3D Physics 集成 NVIDIA PhysX,因此理解 PhysX 的 Joint 与 Constraint 模型也有助于理解 Unity 中 ConfigurableJoint 的行为。1
一、为什么需要 Active Ragdoll?
Active Ragdoll 最重要的设计动机,并不是“让角色倒下时更漂亮”。
它真正解决的是:
预先制作好的动画,与不可预测的物理世界之间存在根本矛盾。
1.1动画擅长描述动作,却不擅长解决现实
传统动画角色大致可以理解为:
Animator 根据当前状态计算每根骨骼的 Pose:
Idle
Walk
Run
Punch
Reload
Climb然后这些 Pose 直接成为角色骨骼的最终结果。
这种模型有一个巨大的优点:
确定。
动画师制作什么,玩家就看到什么。
但它同时隐含了一个前提:
世界最好不要强烈反对这段动画。
假设角色正在挥拳。
动画告诉 Forearm:
接下来 100 ms 内继续向前旋转。
但此时前方突然出现一堵墙。
动画系统和物理世界给出了两个互相冲突的要求:
Animation:
手应该继续向前。
Physics:
这里已经有墙了。如果 Animation 拥有绝对控制权,常见结果就是:
- 手穿进墙中;
- 身体穿过桌面;
- 脚滑过地面;
- 被重物撞击后仍继续播放原有动作;
- 玩家无法真正通过物理作用改变角色姿态。
当然,我们可以不断在 Animator 外面增加补丁:
Foot IK
Hand IK
Hit Animation
Procedural Lean
Wall Detection
Animation Layer
Ragdoll Blend这些技术都很有价值。
但随着交互自由度增加,会出现一个组合爆炸问题。
如果一个角色有:
- 5 种当前动作;
- 8 个撞击方向;
- 4 种撞击强度;
- 6 种环境形态;
- 4 种身体状态;
哪怕粗暴相乘,也已经得到:
种组合。
真实沙盒、近战和 VR 游戏的状态空间远大于此。
这就是 Active Ragdoll 特别适合物理沙盒的原因:
不再试图为所有结果制作动画,而是定义产生结果的规则。
EA/Frostbite 在 GDC 2018 的 Driven Ragdoll 分享中就把这种能力描述为获得 emergent behaviors:角色既能够追踪动画,又能对实际交互做出动态反应,从而减少必须依靠大量固定动画覆盖所有情况的压力。2
1.2Passive Ragdoll 解决了物理,却失去了行动
普通 Ragdoll 则几乎是反过来的:
角色由若干刚体组成:
Pelvis
├─ Spine
│ ├─ Head
│ ├─ Left Arm
│ └─ Right Arm
├─ Left Leg
└─ Right Leg每一块主要身体通常拥有:
Rigidbody
Collider
Joint这时最终姿态由 Physics 决定。
角色终于拥有了:
- 重量;
- 惯性;
- 碰撞;
- 摩擦;
- 关节限制;
- 对外力的自然响应。
但它不会主动完成任何动作。
普通 Ragdoll 很擅长:
被世界作用。
却不擅长:
主动作用于世界。
Active Ragdoll 所增加的,就是这第二种能力。
1.3三种角色模型真正不同的是“谁拥有最终控制权”
可以把三种系统放到一起:
| 模型 | 动画 | 物理 | 最终姿态由谁决定 |
|---|---|---|---|
| Animation Character | 强 | 弱 / 辅助 | Animation |
| Passive Ragdoll | 无主动控制 | 强 | Physics |
| Active Ragdoll | 提供目标 | 强 | Physics + Controller |
Active Ragdoll 最重要的转变不是:
Animator + Rigidbody而是:
Animation = Intent
Physics = Reality动画描述意图。
物理决定现实。
这也是理解整篇文章最重要的心智模型。
Active Ragdoll 并不是想消灭动画,而是在重新定义动画的权力:
动画可以提出要求,但不再拥有无条件执行要求的能力。
二、Active Ragdoll 的核心架构:让身体追逐一个目标
一种最容易理解、也最常见的 Active Ragdoll 架构,是同时维护:
- Target Skeleton
- Physical Skeleton
它们看起来像两具重叠的人体,但职责完全不同。
2.1Target Skeleton:角色想做什么
Target Skeleton 通常仍然可以使用正常 Animator:
Animator
↓
Idle / Walk / Punch / Reload
↓
Target Pose它不必承担主要的物理碰撞。
它只回答一个问题:
如果现实世界没有阻碍,我希望身体现在是什么姿势?
Target Pose 也不一定只能来自动画。
它可以继续被:
- IK;
- Foot Placement;
- Aim;
- Procedural Animation;
- Balance Controller;
- 玩家 Tracking;
进一步修改。
因此一个完整 Target Pipeline 可能是:
2.2Physical Skeleton:角色实际上做到了什么
另一套 Skeleton 则真正存在于物理世界:
Physical Bone
├─ Rigidbody
├─ Collider
└─ Joint它受到:
Gravity
Collision
Friction
External Force
Joint Limit
Muscle Drive共同影响。
最终渲染角色通常跟随这套 Physical Skeleton。
于是整个系统变成:
注意最后一条反馈:
Physical Skeleton → Controller非常重要。
Controller 不只是知道:
目标在哪里?
还必须知道:
我现在在哪里?
只有这样才能计算误差。
2.3Active Ragdoll 本质上是闭环控制
我们拥有:
和:
控制器计算两者之间的误差,再产生 Force / Torque:
这就是典型的:
Closed-loop Control System——闭环控制系统。
如果 Physical Arm 因为撞墙而偏离 Target Arm:
Target Arm
\
\
\
Wall █████
Physical Arm
|
|误差增大。
Controller 就会尝试产生更大的恢复力矩。
但如果墙仍然挡在那里,Physics Solver 不会允许它简单穿过去。
于是最终姿态来自:
Muscle
+
Joint
+
Wall Contact
+
Friction
+
Inertia之间的共同求解。
这就是为什么 Active Ragdoll 能够自然产生普通动画难以覆盖的结果。
2.4Active Ragdoll 不等于 Animation / Ragdoll Blend
这里必须区分另一个常见技术:
Animation Pose ─┐
├─ Blend → Final Pose
Ragdoll Pose ───┘例如:
这种方法非常适合:
- 动画到死亡 Ragdoll 的平滑过渡;
- 部分身体物理化;
- Ragdoll Recovery。
但其核心仍然是:
混合两个已有的 Pose。
Active Ragdoll 则是:
Target Pose
↓
Controller
↓
Force / Torque
↓
Physics Solver
↓
Physical PoseTarget Pose 并不会直接成为最终 Pose。
三、肌肉的本质:反馈控制、PD Controller 与 Joint Drive
做到最简单的 Active Ragdoll Demo 并不困难。
真正重要的是理解:
Joint 为什么能够“像肌肉一样”把身体拉向动画?
答案来自控制理论。
3.1从姿态误差产生力矩
先考虑一个只有单一旋转轴的关节。
当前角度:
目标角度:
当前角速度:
目标角速度:
一个基础 PD Controller 可以写成:
其中:
- :控制器输出的力矩;
- :Proportional Gain;
- :Derivative Gain。
如果目标角速度为 0:
可以把两部分直观理解为:
P:离目标越远,拉得越用力
D:移动得越快,越努力把它刹住所以:
P 很像 Spring。
D 很像 Damper。
NVIDIA PhysX 对 D6 Joint Drive 的定义正是这种形式:Drive 是一个带 Force Limit 的阻尼弹簧,其基本关系写作 stiffness * positionError + damping * velocityError;PhysX 也支持把 Drive 配置为 Acceleration Drive。5
3.2为什么只有 Spring 会疯狂振荡
假设一只手臂需要从:
0°旋转到:
90°如果只有 Spring:
0° → 90° → 115° → 76° → 101° → ...身体会不断越过目标。
Damping 的作用就是吸收这种速度:
Spring:
快回去!
Damper:
别冲那么快。对于最简单的一自由度质量—弹簧系统,临界阻尼满足:
对于旋转系统,更合适的直觉是把质量换成对应轴上的转动惯量:
但一个完整 Ragdoll 显然远比单自由度系统复杂:
- Joint 互相连接;
- 惯性是三维张量;
- 身体不断发生接触;
- 多个 Constraint 同时作用;
- Solver 只是有限次迭代求解。
所以这两个公式更适合作为理解 Spring 与 Damping 关系的直觉,而不是直接生成最终游戏参数的万能公式。
3.3为什么 Spring 越大并不一定越“强”
Active Ragdoll 调参最常见的路径之一是:
身体太软
↓
Spring × 10
↓
还是不够
↓
再 × 10
↓
角色起飞这是因为 Joint Drive 并不是独立存在的。
实际系统是:
Stiffness
+ Damping
+ Maximum Force
+ Mass
+ Inertia
+ Time Step
+ Solver Iterations
+ Collision Constraints共同作用。
Stiffness 越高,意味着:
Solver 必须在一次 Physics Step 内纠正更强烈的误差。
如果误差很大、时间步又很长,就可能要求身体瞬间产生极端速度变化。
结果并不是“更稳定”,反而可能是:
- 高频振荡;
- Joint Separation;
- Collider 穿透;
- Constraint Solver 无法收敛;
- 整具身体突然获得巨大能量。
因此 Active Ragdoll 的第一条调参原则应该是:
不要孤立地调 Spring。
3.4三维旋转不能简单做减法
位置误差很好理解:
Rotation 则不能简单写:
target.eulerAngles - current.eulerAngles因为:
1°和:
359°实际上只差:
2°而不是 358°。
三维旋转还涉及:
- Quaternion;
- Local Space;
- Parent Space;
- Joint Space;
- Swing / Twist。
概念上通常先得到 Quaternion Error:
然后从 得到旋转轴与角度,或者由物理引擎内部直接完成 Quaternion / Swing-Twist Drive。
这一点也是为什么:
Active Ragdoll 中最危险的问题往往不是 Spring,而是坐标空间。
3.5Unity 中 ConfigurableJoint 如何对应这些概念
Unity 6.0 的 ConfigurableJoint 提供了:
targetRotationtargetAngularVelocityangularXDriveangularYZDriveslerpDrive
等接口,并允许在 X/YZ Drive 和 Slerp Drive 之间选择旋转驱动模式。JointDrive 则包含 positionSpring、positionDamper、maximumForce 与 useAcceleration。67
因此概念映射大致可以理解为:
| 控制理论 | Unity Joint |
|---|---|
| Target Pose | targetRotation |
| Target Angular Velocity | targetAngularVelocity |
positionSpring | |
positionDamper | |
| Actuator Limit | maximumForce |
| Force / Acceleration Model | useAcceleration |
Slerp Drive 会整体驱动三个角自由度,而 X/YZ Drive 则更适合需要分别考虑不同旋转自由度的情况。PhysX 的 D6 Joint 同样区分 Swing/Twist 与 SLERP Angular Drive。5
3.6最容易踩的坑:targetRotation 不是 Animator Rotation 的简单复制
下面这样的代码非常诱人:
joint.targetRotation = targetBone.localRotation;但通常不能直接成立。
因为至少存在三个不同空间:
Bone Local Space
↓
Joint Frame
↓
Connected Body / Constraint SpaceConfigurableJoint 的 axis 和 secondaryAxis 定义了 Joint 自己的参考方向。
因此实际实现通常需要保存:
- Initial Bone Rotation;
- Initial Joint Rotation;
- Joint Axis;
- Connected Body Orientation;
然后把 Animator Pose 转换到 Joint 所理解的坐标系。
如果角色出现:
- 一进入 Play 就爆炸;
- 手臂固定偏 90°;
- 左右手旋转方向相反;
- Twist 看起来完全错误;
- Spring 调多大都不正常;
优先检查:
Joint Space、Axis、Bind Pose 与 Target Rotation 的转换。
不要先把 Solver Iteration 调到 50。
四、Active 之前,先造一具好的 Ragdoll
一个经常被忽略的事实是:
Active Ragdoll 的上限,很大程度由 Passive Ragdoll 的质量决定。
如果关闭所有 Muscle 后,角色本身就:
- 自己振动;
- 关节乱折;
- Collider 不断互相推开;
- 身体比例失真;
- 质量分布极端;
那么 Active Controller 只是在一个错误的物理模型上不断施加更大的力。
4.1Physical Skeleton 是动画骨架的物理抽象,不是复制品
角色 Render Rig 可能拥有:
80 Bones
100 Bones
150 Bones这并不意味着需要同样数量的 Rigidbody。
一个游戏角色常见的 Physical Skeleton 可能只抽象:
Pelvis
Spine
Chest
Head
UpperArm × 2
Forearm × 2
Hand × 2
Thigh × 2
Calf × 2
Foot × 2原因是:
Simulation Model 不需要等于 Render Model。
手指有几十根骨骼,不代表它们都值得进入全身 Ragdoll Solver。
每增加一个 Dynamic Body,都意味着增加:
- Constraint;
- Collision Pair;
- Solver Work;
- 潜在的不稳定源。
EA/Frostbite 在 Driven Ragdoll 的工程分享中也专门讨论了降低 Ragdoll 复杂度以改善性能和输出质量的问题。2
4.2Collider 的目标不是完美贴合 Mesh
一个 Active Ragdoll 的 Collider 更应该表达:
身体参与物理交互时的大致体积。
因此常见组合反而很简单:
| 部位 | 常见 Collider |
|---|---|
| Head | Sphere / Capsule |
| Spine / Chest | Capsule / Box |
| Pelvis | Box / Capsule |
| Upper Arm | Capsule |
| Forearm | Capsule |
| Thigh | Capsule |
| Calf | Capsule |
| Foot | Box / Capsule |
如果为了“更真实”给角色加大量复杂 Convex Collider,往往会增加:
- 细碎 Contact;
- 边缘卡住;
- Self Collision;
- Solver 负担。
Active Ragdoll 需要的不是最高几何精度,而是:
稳定、连续、与 Gameplay 相符的碰撞代理。
4.3Self Collision 是一个设计选择
假设 UpperArm 和 Chest 的 Collider 在 Bind Pose 中稍微重叠。
Joint 说:
UpperArm 应该保持连接。
Contact Solver 说:
两个 Collider 不允许重叠。
于是系统可能陷入:
Joint 拉回来
↓
Collision 推出去
↓
Joint 再拉回来
↓
Collision 再推因此相邻身体部位常常应该忽略彼此碰撞,例如:
UpperArm ↔ Chest
Forearm ↔ UpperArm
Thigh ↔ Pelvis
Calf ↔ Thigh至于:
Hand ↔ Head
Arm ↔ Leg这类非相邻 Self Collision 是否开启,就取决于玩法需求。
完整 Self Collision 并不天然意味着“更真实”。
4.4质量与惯性决定了身体是否像一个整体
如果所有 Bone 都设成:
mass = 1会得到一具非常奇怪的人。
人体质量主要集中在:
- 躯干;
- 骨盆;
- 大腿。
手和前臂则轻很多。
游戏并不需要严格复刻医学人体模型,但应该拥有合理的相对质量结构。
更重要的是:
相邻 Joint 两侧不要拥有极端的有效质量差。
PhysX 文档专门讨论了 Joint Mass / Inertia Scaling:让 Joint 两侧看到更接近的有效质量与惯性,可以帮助 Constraint Solver 更快收敛、减少“橡皮”或抽动,但这种 Scaling 本身是非物理的,会破坏严格的动量与能量关系。8
这很好地体现了游戏物理的重要原则:
视觉稳定性和严格物理真实性并不是同一个目标。
除了 mass,还不要忽视:
Center of Mass
Inertia Tensor两个同样 5 kg 的物体,如果质量分布不同,对同样 Torque 的旋转响应也完全不同。
4.5Joint Limit 定义的不是动画范围,而是身体可行域
如果 Joint Limit 太宽:
角色会出现人体不可能的折叠。
如果太窄:
普通动画本身就可能不断撞击 Limit。
于是 Controller 一边说:
Follow Target!Joint Limit 同时说:
You cannot rotate further.两个 Constraint 长时间冲突,就会制造额外振荡。
所以 Joint Limit 的设计目标不是:
把角度限制得“医学上最真实”。
而是找一个同时满足:
Animation Coverage
Physical Plausibility
Solver Stability
Gameplay的可行范围。
五、稳定性:为什么 Active Ragdoll 总是在抖?
当一个角色开始运行时,Physics Solver 看到的并不是“一个人”。
它看到的是一个巨大的 Constraint Problem:
15 Rigidbody
14 Joint
14 Joint Drive
多个 Joint Limit
Ground Contacts
Self Contacts
Friction
External Contacts
Grab Constraint每个 Physics Step 中,这些条件都试图同时成立。
但实时物理引擎并不会无限精度地求出完美解析解。
它只能在有限 CPU 时间里:
通过有限迭代逼近一个足够好的解。
因此 Active Ragdoll 的许多“诡异 Bug”,其实是 Constraint System 没有在当前预算下得到稳定解。
5.1时间步是稳定性的第一层预算
Unity 的物理模拟使用固定时间步,Time.fixedDeltaTime 定义 Fixed Update 与默认 Physics Step 的游戏时间间隔。Unity 官方文档也明确建议物理模拟使用较小且一致的固定步长,因为随帧率变化的大时间步会降低准确性并更容易造成不稳定。9
例如:
意味着:
50 Hz而:
意味着:
100 Hz当 Controller 很硬时,更小的 意味着:
每一步需要纠正的误差通常更小。
因此:
High Stiffness
+
Large Time Step往往是危险组合。
但提高 Physics Frequency 同样意味着:
每秒需要做更多次碰撞与 Solver 工作。
所以这是典型的:
Stability ↔ CPU Cost权衡。
5.2Animator 与 Physics 还必须处于正确的时间关系
Active Ragdoll 不是只有 Physics。
还存在:
Input
Animator
IK
Target Skeleton
Joint Drive
Physics
Render如果 Physics 每次都在追:
上一次动画更新留下的 Target Pose,
就可能产生额外滞后和抖动。
Unity 6.0 的 Animator 可以选择 Normal 或 Fixed 更新模式;Fixed 模式在 Fixed Update Loop 中评估动画。10
这并不意味着:
Active Ragdoll 一定必须把 Animator 设置成 Fixed。
真正重要的是:
你必须明确 Animation Evaluation、Target Pose Capture 和 Physics Step 的先后关系。
概念上理想的数据流应该是:
而不是让这些阶段凭偶然顺序互相读取旧状态。
5.3Solver Iterations 是精度预算,不是修复按钮
Unity 的 Rigidbody.solverIterations 和 solverVelocityIterations 会影响 Joint 与 Contact 的求解精度;Unity 文档也明确指出,在 Jointed Rigidbody 或 Ragdoll 发生碰撞后表现过于松散时,提高 Velocity Iterations 可能有所帮助。11
对于这样的长约束链:
Pelvis
↓
Chest
↓
UpperArm
↓
Forearm
↓
Hand
↓
Grabbed Object更高 Solver Budget 往往确实有帮助。
但它解决不了:
Wrong Joint Axis
Wrong Target Rotation
Collider Initial Penetration
Impossible Joint Limit
Extreme Drive所以:
先修模型,再提高求解预算。
5.4Projection 是保险措施,不是 Controller
Unity 的 Joint Projection 可以在 Constraint 偏离过大时把 Joint 拉回合法区域。
但 Unity 文档明确指出:
Projection 不是物理过程,不保持动量,也不保证遵守碰撞几何;在 Joint 形成 Cycle 时,Projection 甚至可能无法执行。12
因此它应该被理解为:
Emergency Correction而不是:
Primary Muscle System如果 Projection 每一帧都在拯救角色:
说明底层设计大概率还有别的问题。
5.5Constraint Loop:抓取系统为什么特别容易炸
假设角色右手抓住一个箱子:
Chest
↓
UpperArm
↓
Forearm
↓
Hand
↓
Grab Joint
↓
Box这只是 Constraint Chain。
如果两只手同时抓住一个方向盘:
Left Arm ── Left Hand ──┐
↓
Steering Wheel
↑
Right Arm ─ Right Hand ─┘而两条手臂又通过 Chest 连接:
Constraint Loop 出现了。
现在系统同时要求:
- 左手跟随动画;
- 右手跟随动画;
- 双手留在方向盘上;
- 方向盘遵守自己的 Joint;
- 胸口追踪 Target;
- 所有 Collider 不穿透。
这些要求可能根本不存在完美同时满足的解。
解决方法往往不是:
把所有 Spring 调到 100000。
而是主动引入 Compliance——柔顺性:
- Hand Drive 不必绝对精确;
- Grab Joint 有 Force Limit;
- Shoulder 可以承担一部分误差;
- 物体过重时身体应该被拖动;
- 力过大时 Grab 可以断开。
这是一条很重要的 Active Ragdoll 设计原则:
允许误差,往往比消灭误差更稳定。
5.6一个比“随机调参数”更有用的排查顺序
| 现象 | 首先检查 |
|---|---|
| Play 后立即爆炸 | Initial Penetration、Joint Space、Axis |
| 肢体始终偏转 | Bind Rotation、Joint Frame |
| 高频小抖动 | Stiffness、Damping、Time Step |
| Joint 被明显拉长 | Mass Ratio、Solver Budget |
| 快速动作追不上 | Drive Strength、Angular Velocity Limit |
| 撞墙后越来越暴躁 | Target Root 是否继续远离 Physical Root |
| 双手抓物后爆炸 | Constraint Loop、Grab Compliance |
| 倒地后疯狂抽搐 | Knockdown State 是否仍在全力追站立 Pose |
Unity 的 Rigidbody.maxAngularVelocity 会限制 Rigidbody 的最大角速度,官方说明其目的之一就是避免高速旋转导致数值不稳定;因此“快速动画追不上”时它值得检查,但也不应简单无限提高。13
六、从“追 Pose”到“控制身体”:站立与行走
如果我们已经能够稳定追踪:
Idle Pose是不是就意味着角色会站立?
答案是:
不一定。
这是 Active Ragdoll 从技术 Demo 走向真正 Character Controller 的分水岭。
Pose Control 和 Balance Control 是两个不同问题。
6.1一个站立 Pose 可能仍然在物理上必然倒下
角色由多个刚体组成。
整个系统的质心可以表示为:
其中:
- 是第 个刚体质量;
- 是其质心位置。
双脚与地面接触时,可以从 Foot Contact 构造一个支撑区域:
Support Polygon。
对于准静态情况,一个非常有用的判断是:
COM 的垂直投影是否位于支撑区域内?
● COM
|
|
↓
[ Left Foot ][ Right Foot ]
└──── Support Region ─────┘如果 COM 投影远离支撑区域:
●
|
↓
[ Left Foot ][ Right Foot ]无论 Idle Animation 看起来多么像“站姿”,身体都很难仅靠原地保持。
Support Polygon、ZMP 等概念长期用于双足机器人平衡研究;但需要注意,COM 投影位于支撑区域主要是一个很有价值的静态/准静态直觉,并不能完整描述动态平衡。动态行走还涉及惯性、角动量、接触力以及 Zero-Moment Point 等条件。14
6.2为什么角色最终必须学会“迈一步”
假设角色被轻轻推了一下。
它可以通过:
- Ankle;
- Hip;
- Spine;
调整姿态,把 COM 拉回来。
但如果扰动足够大:
Feet
[--------]
● COM
→ velocity仅改变上半身姿势已经救不回来。
真正的人会改变:
支撑区域本身。
也就是:
迈一步。
于是系统从:
Pose Tracking升级为:
Balance Control再升级为:
Stepping Control一个概念性的 Controller 可以是:
这里发生了一个非常重要的变化:
一开始:
Animation 决定 Pose。
现在:
Physics State 反过来修改 Animation / Target Pose。
这才是完整闭环。
6.3Walking 不是“播放 Walk 动画”
如果普通 Animator 播放 Walk:
动画往往已经假设:
Root 向前移动
+
脚按预定轨迹移动但 Physical Foot 有真实的:
- Contact;
- Friction;
- Velocity;
- Mass。
于是可能出现:
Animation:
脚应该向后划。
Physics:
这只脚正在承担身体重量,应该抓住地面。结果就是经典的:
滑冰。
因此物理步行通常必须区分:
Stance Foot
正在承担支撑的脚。
Swing Foot
正在移动到下一个落脚位置的脚。
Phase A:
Left = Stance
Right = Swing
Phase B:
Left = Swing
Right = Stance这意味着真正的 Physical Locomotion 已经不只是 Animation Playback,而是在处理:
Gait
Foot Contact
Foot Target
Pelvis
Balance
Desired Velocity之间的关系。
6.4IK 没有因为 Active Ragdoll 而失去意义
一个非常合理的 Pipeline 是:
Animation
↓
Foot / Hand IK
↓
Target Skeleton
↓
Active Ragdoll
↓
Physical SkeletonIK 回答:
脚最好放在哪里?
Active Ragdoll 回答:
真实身体在当前物理环境下能做到多少?
两者不是竞争关系。
它们解决的是不同层次的问题。
6.5Root Motion 应该从“位移命令”变成“运动意图”
普通 Root Motion 隐含:
Animator Root Position
=
Character Position但 Active Ragdoll 必须面对:
Animation:
向前 4 m/s。
Physics:
两米外是一堵墙。如果直接应用 Root Motion:
Physical Character 最终仍会被 Transform 拖动。
如果完全忽略 Root Motion:
动画步态和世界运动又可能失去关系。
一种更符合 Active Ragdoll 思想的办法是把 Root Motion 解读为:
Desired Velocity或者:
Desired Displacement然后让 Locomotion Controller 尝试通过物理实现它。
再次回到那条核心原则:
Animation 描述意图,Physics 决定现实。
七、真正让 Active Ragdoll 有价值的行为:受击、倒地、抓取与恢复
如果 Active Ragdoll 最终只是:
用更昂贵的方法播放 Walk Animation,
那么它的价值非常有限。
它真正开始发光,是从外部世界能够不断改变角色开始。
7.1Hit Reaction:不要播放“被打”,让身体真的被打
传统 Hit Reaction 通常需要:
HitFront
HitBack
HitLeft
HitRight
Head
Chest
Arm
Leg
Light
HeavyActive Ragdoll 则可以让 Collision / Impulse 本身成为动作的一部分:
Run Control
+
Impact
+
Balance
+
Muscle
+
Foot Contact最终共同产生结果。
轻击:
身体晃动,然后恢复。
重击:
Spine 偏转,脚开始调整。
更强的攻击:
Balance 失败,进入 Knockdown。
这种反应不是从数据库里选择的一段固定 Pose,而是从当前状态中生成。
这正是 EA/Frostbite 所强调的 Driven Ragdoll 的价值之一。2
7.2Muscle 不应该只有 On / Off
最粗糙的设计通常是:
bool isRagdoll;于是:
false = Active
true = Passive但更加自然的模型是:
其中:
0 = Passive
1 = Fully Driven进一步甚至可以:
Spine Strength
Arm Strength
Leg Strength
Neck Strength全部独立变化。
例如胸口受到重击:
Spine
1.0 → 0.35 → 0.5 → 0.7 → 1.0角色表现出来的就不是:
突然全身断电。
而是:
胸口一瞬间没有撑住,然后重新获得控制。
这也是为什么更成熟的 Active Ragdoll 更适合用:
Muscle State而不是:
Ragdoll Switch来思考。
7.3Knockdown 的关键是知道什么时候应该放弃平衡
一个 Character Controller 如果永远试图保持站立,会出现很荒谬的状态:
角色已经横着飞出去
+
双腿仍然全力追 Run Pose因此需要判断:
什么时候当前姿态已经不可恢复?
可能参考:
Pelvis Height
Body Orientation
COM Error
Linear Velocity
Angular Velocity
Foot Contacts
Impact Magnitude一旦进入 Falling / Knockdown:
可以主动改变 Muscle Configuration:
| 状态 | Spine | Arm | Leg | 目的 |
|---|---|---|---|---|
| Normal | 高 | 中高 | 高 | 正常控制 |
| Stagger | 中 | 中 | 中 | 恢复平衡 |
| Falling | 低 | 中高 | 低 | 允许倒下、保护身体 |
| Unconscious | 极低 | 极低 | 极低 | 接近 Passive |
| Dead | 0 | 0 | 0 | Passive Ragdoll |
这里的数值不重要。
真正重要的是:
不同状态可以拥有不同身体控制策略。
7.4Falling 也可以是主动行为
现实中的人开始跌倒后,并不会瞬间让所有肌肉归零。
可能会:
- 伸手撑地;
- 保护头部;
- 收缩躯干;
- 抓住栏杆;
- 调整腿部。
于是 Falling 本身也可以拥有 Controller:
Leg Control ↓
Arm Protection ↑
Head Protection ↑
Grab Opportunity ↑这时系统已经从:
Pose Driven Ragdoll
开始进入:
Physical Character Behavior。
7.5Get Up 为什么比倒下难得多
倒下很容易:
Muscle ↓
Gravity
↓
Fall站起来则必须解决:
当前 Physical Pose 与 Get-Up Animation 根本不是从同一个姿态开始。
角色可能:
- 仰卧;
- 俯卧;
- 侧躺;
- 卡在墙边;
- 一只腿搭在箱子上;
- 一只手压在身体下面。
第一步通常是估计当前身体朝向:
Supine
Prone
Side然后选择相应 Get-Up Strategy。
但最重要的步骤不是选 Animation Clip。
而是:
先把 Target Skeleton 对齐 Physical Body。
如果 Physical Pelvis 在 A:
A而 Animator Get-Up Root 在 B:
B直接播放动画意味着 Joint Controller 会试图:
瞬间把身体拖到 B。
正确流程通常更接近:
Wolfire 在 Overgrowth 的开发记录里就公开记录过从 Ragdoll 站起、Ragdoll Recovery,以及 Active Ragdoll 在狭窄空间中的改进。15
7.6Grab 与 Climb 会把角色变成一个更大的物理系统
角色没有抓东西时:
Body是一套内部 Constraint Graph。
当手抓住环境:
Body
↓
Hand
↓
World角色突然和世界成为了同一套 Constraint System。
攀爬尤其明显:
Left Hand Anchor
Right Hand Anchor
Body Weight
Leg Contacts此时手不只是:
跟随 Hand Target。
它还在:
承担整具身体的重量。
因此一个成熟 Grab System 往往需要根据:
- Object Mass;
- Hand Force;
- Shoulder Load;
- Body Position;
动态调整控制策略。
7.7VR 把“控制权冲突”推到了极致
VR 手柄 Tracking 给出:
我的真实手现在必须在这里。
Physics 却可能说:
那个位置在墙后面。
于是产生:
Tracked Hand →→→→
█ Wall
Physical Hand ──|如果 Tracking 绝对胜利:
手穿墙。
如果 Physics 绝对胜利:
虚拟手和真实手严重分离。
所以 VR Physical Character 的问题,本质上仍然是本文一直讨论的问题:
谁拥有多少控制权?
只不过这次第三方不是 Animator,而是玩家真实身体。
八、从 Active Ragdoll 到 Physical Character System
真正成熟的 Active Ragdoll 最终通常不会只是:
ActiveRagdoll.cs因为“追踪 Pose”只是整个 Physical Character 的底层能力。
8.1一个可维护的系统应该分层
可以把系统划分成:
这里:
ActiveRagdollController
只负责:
Target Pose
→
Joint Target / Muscle DriveBalanceController
负责:
COM
Foot Contact
Lean
Recovery
SteppingLocomotionController
负责:
Desired Velocity
Gait
Foot Target
Pelvis MotionHitReaction
负责:
Impact
→
Local Muscle Change
→
Stagger / KnockdownPhysicalState
负责:
Normal
Stagger
Falling
KnockedDown
GettingUp
Unconscious
DeadGrab / Climb
负责外部 Constraint。
这能避免最后出现一个:
ActiveRagdoll.cs
9000 lines同时处理走路、受击、VR、方向盘和死亡。
8.2几个典型游戏其实代表了不同的设计目标
Active Ragdoll 没有唯一正确答案。
不同游戏只是选择了不同的:
Physics Freedom
↔
Control Precision比例。
8.2.1Human: Fall Flat:把“不精确”变成玩法
Human: Fall Flat 的开发者曾公开说明:
Gang Beasts 和 Octodad 让他意识到 Fully Active Ragdoll 可以成为完整的 3D 角色系统,而不只是 FPS 中角色死亡后的效果;而 Overgrowth 关于 Procedural Animation 的资料则帮助其开始早期实验。4
Human: Fall Flat 的高明之处并不是消灭:
- 摇晃;
- 抓不准;
- 身体迟钝;
- 控制误差。
而是把这些特性直接设计成 Gameplay。
技术“缺陷”变成了游戏规则。
8.2.2Overgrowth:从 Ragdoll 走向 Physical Combat
Wolfire 在 2009 年开发 Overgrowth 时就明确写到,他们开始研究:
physically simulated, but not totally passive
的 Active Ragdoll。3
后续开发日志又不断出现:
- active ragdoll;
- ragdoll recovery;
- leg IK;
- climbing;
- standing up from ragdoll;
这些内容。
它代表了另一条路线:
Active Ragdoll 不只是搞笑物理,而可以服务于战斗、跑酷和动态身体反馈。
8.2.3EA / Frostbite:Driven Ragdoll 作为规模化动画系统的一部分
Frostbite 的方案很值得注意,因为它不是一个“物理玩具游戏”。
GDC 2018 的分享直接讨论了:
- Animation Following;
- Interaction Response;
- Emergent Behavior;
- Performance;
- Bad Pose Reduction;
- Feedback into Animation;
- Networking;
这说明在大型商业角色系统中,Driven Ragdoll 真正的问题早已不是:
Joint 怎么转?
而是:
怎样让 Physical Character 与整个 Animation Pipeline 共存?2
8.2.4GTA IV / Euphoria:从“追 Pose”继续走向“执行行为”
GTA IV 使用了 NaturalMotion 的 Euphoria。同期公开资料把 Euphoria 描述为一种基于 Dynamic Motion Synthesis 的实时角色动画系统,它模拟角色的 Motor Control、Muscles 和 Biomechanics,使角色能够根据实际情况动态生成运动。16
因此最好不要简单写:
Euphoria = Active Ragdoll它更接近 Active Ragdoll 再向上一层发展的方向。
普通 Pose Driven Ragdoll 的上层命令是:
把手放到这里。Behavior Driven Physical Character 的上层命令则可以逐渐抽象成:
Stay Standing
Protect Head
Reach Object
Recover Balance然后下层 Controller 自己决定身体如何完成它。
因此 Physical Character 可以粗略理解为几个层次:
越向右:
上层描述“目的”。
而不是描述每根骨头下一帧应该在哪里。
九、真正困难的不是 Ragdoll,而是“权力分配”
做到最后,会发现 Active Ragdoll 所有技术问题都在反复回到同一个核心矛盾。
角色中至少有三个系统在表达自己的要求:
Gameplay:
玩家按 W,我要向前。
Animation:
当前应该播放 Run。
Physics:
前面是一堵墙。三者都没有错。
真正需要设计的是:
谁拥有多少权力?
普通 Animation Character 更接近:
Gameplay > Animation >>> PhysicsPassive Ragdoll:
Physics >>> EverythingActive Ragdoll:
Gameplay
↕
Animation
↕
Physics而所谓:
- 手感;
- 重量感;
- 响应速度;
- 物理真实性;
- 稳定性;
很大程度上都是这套权力结构的结果。
9.1“物理越多越好”是一个危险目标
如果 Physics 权力过高:
角色可能很有重量感,却:
- 很难控制;
- 响应迟钝;
- 经常跌倒;
- 无法可靠完成 Gameplay Action。
如果 Controller 权力过高:
角色非常精准,却:
- 像普通动画角色;
- 外力没有存在感;
- 撞击缺少重量;
- Physical Interaction 变成视觉装饰。
所以真正成熟的 Physical Character 几乎必然是:
Hybrid System。
它会在不同场景下主动改变控制权。
例如:
普通移动:
Gameplay / Animation 权力高
轻微受击:
Physics 权力增加
Knockdown:
Physics 权力显著增加
Get Up:
Animation / Controller 逐渐重新接管
VR Hand Contact:
Tracking 与 Physics 协商这比追求某个固定的:
“80% Physics”有意义得多。
十、从 Demo 到可用系统:推荐实现路线
第一次实现 Active Ragdoll 时,最危险的目标就是:
一上来做 Euphoria。
因为这会同时引入:
Rigid Body Physics
Joint Solver
PD Control
Animation
IK
Balance
Walking
Grab
Get Up
Procedural Behavior任何一层错误都会表现成:
“角色好像就是很怪。”
更可靠的方法是逐层建立能力。
10.1Phase 1:Passive Ragdoll
只做:
- Rigidbody;
- Collider;
- Joint;
- Joint Limit;
- Mass Distribution;
- Self Collision。
此时关闭所有主动 Drive。
目标不是好看,而是:
Ragdoll 本身不会无缘无故爆炸。
10.2Phase 2:Static Pose Tracking
增加 Target Skeleton 和 Joint Drive。
先只追一个静态 Pose:
T-Pose
↓
Idle Pose解决:
- Joint Space;
- Bind Rotation;
- Stiffness;
- Damping。
不要碰 Walking。
10.3Phase 3:Animation Following
让普通 Animator 驱动 Target Skeleton。
开始测试:
Idle
Simple Gesture
Slow Walk同时解决 Target Root 与 Physical Root 的关系。
10.4Phase 4:Muscle System
把:
bool isRagdoll升级成:
Per-Bone Muscle Strength支持:
- Partial Ragdoll;
- Local Hit;
- Stun;
- Falling。
10.5Phase 5:Hit、Knockdown 与 Recovery
让外部 Impulse 真正改变身体。
建立:
Normal
→ Stagger
→ Falling
→ KnockedDown
→ GettingUp完整状态环。
到这里,一个 Active Ragdoll 已经具有非常明显的游戏价值。
10.6Phase 6:Locomotion
再开始处理:
- Foot Contact;
- Foot IK;
- Stance / Swing;
- Root Motion;
- Desired Velocity。
此时你会第一次真正遇到:
Pose Tracking 并不等于 Walking。
10.7Phase 7:Balance 与 Stepping
计算:
- COM;
- Support Region;
- Body Velocity;
- Fall Prediction。
让系统能够主动决定什么时候改变 Foot Target。
这一步开始真正进入 Physical Character Controller。
10.8Phase 8:Grab、Climb、Vehicle 与 VR
最后处理复杂 Constraint:
Two-Hand Grab
Climbing
Steering Wheel
Seat
Tracked Hand
Tracked Head这些问题建立在前面的身体控制已经足够稳定之后,才值得解决。
十一、什么时候应该用 Active Ragdoll?
Active Ragdoll 特别适合:
- Physics Sandbox;
- VR;
- 近战;
- 抓取与攀爬;
- 高自由度环境交互;
- Destruction;
- Vehicle Interaction;
- Emergent Gameplay。
因为这些游戏真正的问题都是:
世界状态无法被提前穷举。
但如果游戏要求的是:
- 极低输入延迟;
- 高度精确;
- 动作结果严格可预测;
- 竞技公平性;
- 很少发生复杂身体交互;
那么完整 Active Ragdoll 未必值得。
一个:
Character Controller
+
Animation
+
IK
+
Procedural Reaction
+
Partial Ragdoll可能更简单、更稳定,而且更符合游戏目标。
Active Ragdoll 并不是 Animator 的“升级版”。
它只是选择了另一个问题:
当角色必须真正成为物理世界的一部分时,如何仍然让他拥有行动能力?
十二、总结:动画描述意图,物理决定现实
如果只记住一个模型,可以记住:
Traditional Animation
Animation
↓
Final PosePassive Ragdoll
Physics
↓
Final Pose而 Active Ragdoll 是:
Animation / AI / IK
↓
Target Pose
↓
Pose Error
↓
Muscle Controller
↓
Force / Torque
↓
Physics Solver
↓
Physical Pose
↑
└──── Feedback从这里,几乎整套系统都可以自然推导出来。
因为有 Pose Error,所以需要 PD Controller。
因为 Controller 输出 Force / Torque,所以需要考虑 Mass 和 Inertia。
因为身体由多个 Joint 连接,所以需要 Constraint Solver。
因为 Solver 只有有限预算,所以会出现 Time Step、Iterations 和稳定性问题。
因为一个站姿 Pose 并不保证不倒,所以需要 Balance。
因为 Balance 最终无法只靠扭动身体恢复,所以需要 Stepping。
因为脚真的接触地面,所以 Walking 必须考虑 Stance 与 Swing。
因为身体真的受到外力,所以 Hit Reaction 可以自然涌现。
因为角色可能真的倒下,所以必须解决 Get Up。
因为手真的抓住物体,所以会形成新的 Constraint Graph。
继续向上抽象以后,系统甚至会从:
“把身体变成这个 Pose”
走向:
“让身体完成这个行为”。
于是一个看似属于游戏动画的问题,最终连接到了机器人学里的同一个基本问题:
如何控制一个受到物理规律约束的多刚体系统?
区别在于,机器人不能作弊。
游戏可以。
我们可以:
- 调整质量;
- 修改惯性;
- 提高摩擦;
- 添加虚拟 Torque;
- 偷偷修正 COM;
- 改变 Muscle Strength;
- 使用 IK;
- 使用 Animation;
- 必要时允许非物理 Correction。
这不是缺点。
恰恰相反,这是游戏角色设计最大的自由。
真正的目标从来不是:
构造一个最严格的人体动力学模拟器。
而是:
构造一个足够服从物理,因此能够产生可信而丰富的交互;又足够服从游戏设计,因此仍然稳定、响应迅速并且好玩的角色。
这才是 Active Ragdoll 最核心的设计问题。
也是它真正迷人的地方。
注释
-
Unity Documentation,Physics system / Built-in 3D Physics(Unity 6.0)。Unity 官方说明面向 GameObject 的内置 3D Physics 集成 NVIDIA PhysX,用于 Rigidbody、Collider、Joint 和 Ragdoll 等系统。 ↩
-
Jalpesh Sachania / EA Frostbite,Physics Driven Ragdolls and Animation at EA: From Sports to Star Wars,GDC 2018。该分享讨论 Driven Ragdoll 的动画追踪、交互响应、涌现行为、性能、异常 Pose、动画反馈与网络同步问题。 ↩ ↩2 ↩3 ↩4 ↩5
-
David Rosen / Wolfire Games,Ragdoll physics - part one,2009。Overgrowth 开发日志中把正在研究的 Active Ragdoll 描述为“physically simulated, but not totally passive”的角色。 ↩ ↩2
-
No Brakes Games / Human: Fall Flat 开发者,Gang Beasts?,Steam Community,2016。开发者说明 Gang Beasts 与 Octodad 展示了 Fully Active Ragdoll 作为完整 3D Character System 的可能性,并提到 Overgrowth Procedural Animation 对早期实现探索的影响。这属于开发者公开社区发言,而非正式技术论文。 ↩ ↩2
-
NVIDIA,PhysX SDK Documentation — Joints / PxD6Drive。PhysX 将 D6 Drive 定义为受 Force Limit 限制的阻尼弹簧,并给出
stiffness * positionError + damping * velocityError的 PD 型关系;Angular Drive 支持 Swing/Twist 与 SLERP 模式。 ↩ ↩2 -
Unity Documentation,ConfigurableJoint / ConfigurableJoint.targetRotation / ConfigurableJoint.slerpDrive(Unity 6.0)。官方 API 定义
targetRotation为 Joint 的目标 Quaternion,并提供 X/YZ 与 Slerp 两类 Rotation Drive。 ↩ -
Unity Documentation,JointDrive(Unity 6.0)。
JointDrive暴露positionSpring、positionDamper、maximumForce与useAcceleration,分别用于目标恢复强度、阻尼、驱动力上限以及 Force/Acceleration Drive 选择。 ↩ -
NVIDIA,PhysX SDK Documentation — Joints: Mass Scaling。官方文档说明使 Joint 两端具有更接近的有效质量和惯性有助于 Solver 收敛并减少 Joint 松软或抽动,但同时指出 Mass/Inertia Scaling 是非物理处理,可能破坏动量与能量关系。 ↩
-
Unity Documentation,Fixed updates / Manually set physics simulation(Unity 6.0)。Unity 建议物理模拟使用固定且一致的时间步,并指出大的可变时间步可能造成更不稳定或不准确的模拟。 ↩
-
Unity Documentation,AnimatorUpdateMode(Unity 6.0)。Animator 支持 Normal 与 Fixed 等更新方式;Fixed 模式在 FixedUpdate Loop 中进行动画评估。 ↩
-
Unity Documentation,Rigidbody.solverIterations / Rigidbody.solverVelocityIterations(Unity 6.0)。官方说明这些属性影响 Rigidbody Joint 与 Collision Contact 的求解精度,提高迭代数可以改善部分 Joint/Ragdoll 碰撞后的误差,但会增加计算成本。 ↩
-
Unity Documentation,ConfigurableJoint projectionMode / projectionDistance(Unity 6.0)。官方明确指出 Projection 用于在 Solver 无法满足 Constraint 时重新对齐 Joint,但它不是物理过程、不保持动量、不保证尊重碰撞几何,而且在形成 Joint Cycle 时可能无法 Projection。 ↩
-
Unity Documentation,Rigidbody.maxAngularVelocity(Unity 6.0)。官方说明该属性限制 Rigidbody 的最大角速度,并指出这一限制用于避免高速旋转导致的数值不稳定。 ↩
-
Miomir Vukobratović、Branislav Borovac,Zero-Moment Point — Thirty Five Years of Its Life,International Journal of Humanoid Robotics,2004;另参见后续 Humanoid Robotics 文献对 Support Polygon、ZMP 与动态平衡的讨论。这里引用这些概念用于解释 Active Ragdoll 的平衡直觉,并不意味着游戏角色必须实现完整 ZMP Controller。 ↩
-
Wolfire Games 的 Overgrowth 开发日志,包括 Overgrowth Alpha 84、Overgrowth a126 video changelog 等。日志记录了 Leg IK、Ragdoll Recovery、从 Ragdoll 站起以及狭窄空间中的 Active Ragdoll 改进。 ↩
-
NaturalMotion / Rockstar 的同期资料以及 Game Developer 对 Euphoria 的报道。GTA IV 确认使用 NaturalMotion Euphoria;公开资料将其描述为基于 Dynamic Motion Synthesis 的实时角色系统,通过 Motor Control、Muscles 与 Biomechanics Simulation 动态合成交互运动。因此本文将它视为比基础 Pose-Driven Active Ragdoll 更广义的 Physical Character / Behavioral Simulation 案例。 ↩
CONTINUE EXPLORING