← ALL ARTICLES

Ragdoll

全库目录221
本文目录9

动画把骨骼摆到当前姿态,物理系统却可能还停在绑定姿态。直接开启动态刚体时,两份状态发生冲突,角色会突然跳动。Ragdoll的切换先建立骨骼与刚体的空间对应,再把速度和控制权交给物理求解器。

骨骼与刚体的对应

骨骼原点常在关节,刚体质心则在肢体中间。记W为世界空间、B为骨骼空间、C为刚体局部空间,TXYT_{XY}将Y空间的坐标变到X空间。这里的变换只含旋转和平移,骨骼缩放须先烘焙到刚体几何或单独处理。离线保存刚体在骨骼中的固定变换 TBCT_{BC},采用列向量时,当前刚体世界变换为 TWC=TWBTBCT_{WC}=T_{WB}T_{BC}。回写动画时用 TWB=TWCTBC−1T_{WB}=T_{WC}T_{BC}^{-1} 恢复骨骼世界变换,再相对父骨骼求局部变换。忽略这个偏移会让碰撞体与皮肤错位。

关节的两个局部锚点分别属于相邻刚体。约束比较它们变到世界空间后的位置和轴向;肘关节只开放合理自由度,角度范围使用引擎规定单位。相邻碰撞体若在初始姿态互相穿透,接触与关节会给出冲突修正,因此先检查资产几何与碰撞过滤,再增加迭代次数。

继承线速度与角速度

使用最近两个正时间间隔采样的刚体质心位置,线速度为 (p1−p0)/Δt(p_1-p_0)/\Delta t。旋转用归一化四元数计算世界空间增量 qd=q1q0−1q_d=q_1q_0^{-1},将其符号调整到标量部分非负,选择短弧。

令增量四元数为 (w,v)(w,\mathbf{v}),角度 θ=2atan2⁡(∣v∣,w)\theta=2\operatorname{atan2}(|\mathbf{v}|,w),角速度为 ω=θv/(∣v∣Δt)\boldsymbol\omega=\theta\mathbf{v}/(|\mathbf{v}|\Delta t),单位弧度/秒;向量部分接近零时取零。这是假定相邻采样间旋转不足半周的短弧估计;快速旋转超过半周时需要更密采样或直接继承动画系统的角速度。直接把四元数四个分量相减除时间,得不到角速度。

text
bodyPose[i] = boneWorld[i] * bodyInBone[i]
linearVelocity[i] = (bodyCenterNow[i]-bodyCenterBefore[i]) / dt
delta = normalize(rotationNow[i] * inverse(rotationBefore[i]))
if delta.w < 0: delta = -delta
angularVelocity[i] = axis(delta) * shortAngle(delta) / dt
enable dynamics after every body and joint has been initialized

这是世界空间机制伪代码;axis与shortAngle按上面的公式求值。若角色刚传送,有限差分会给出极大速度,切换记录必须区分连续动画与离散传送。还要约束最大继承速度,并保存限幅原因。

恢复动画

物理平稳后先根据骨盆朝向选择仰卧或俯卧起身动作,再把角色根放到可站立地面,使起身动画的骨盆与当前物理骨盆接近。保存当前物理姿态,以局部平移插值和四元数插值逐渐过渡到起身动画。

纯表现混合只改变渲染骨骼,物理碰撞体按恢复策略切为运动学或退出;这种方式不保证混合骨架满足动态关节。需要身体在恢复中继续受力时,使用关节驱动追踪动画目标,并限制驱动力矩。两条路径拥有不同的控制权,不能同时让动画直接改动态刚体位置、求解器又计算它的约束。

恢复时先选起身动作首帧根到骨盆的变换T_RB。完整刚体根可由T_WB*inverse(T_RB)回推,但竖直角色胶囊只保留选定朝向的yaw旋转R_WR,不继承倒地骨盆的横滚与俯仰。

起身资产另存首帧骨盆局部的目标站立前向a_B;将R_WB*a_B投到垂直于Up的平面并归一化,作为根的世界前向,结合Up构造R_WR。投影趋零时沿用倒地前记录的角色水平前向;该方向也无效才采用关卡规定的默认朝向。这样yaw有确定的数据来源,不把骨盆任意局部轴直接当站立朝向。设物理骨盆位置为p_WB、动画根内骨盆位置为p_RB,候选根平移取p_WR=p_WB-R_WR*p_RB,使骨盆位置对齐;骨盆朝向差留在捕获姿态中。随后胶囊查询调整根到可站立位置,落点被墙阻挡时延迟恢复或选其他姿态。

根确定后将捕获的每个物理骨骼世界变换变回其父骨骼局部空间,根骨骼则相对这个新根求局部变换;因此权重为零时仍复现原世界姿态,不会随根调整跳动。

纯表现过渡保存物理骨架的局部姿态A,并每帧取起身动作姿态B(t),用随时间从0到1的权重插值位置、短弧插值旋转。权重为0复现捕获姿态,权重为1交给动画;混合期间碰撞控制权按前述策略保持唯一。关节驱动方案则把B(t)转换成相邻刚体的目标相对旋转,驱动求解由 刚体物理求解 维护,不能将表现插值当作力矩求解。

关节目标与驱动力矩

动态恢复需要把动画旋转转换到物理关节坐标。先按骨骼到刚体的固定偏移求每个目标刚体旋转,再乘各自离线保存的关节局部旋转,得到目标关节框架qA_target与qB_target。目标相对旋转为qTarget=inverse(qA_target)*qB_target;当前值同样由物理刚体与关节框架求得qRel=inverse(qA)*qB。省略关节局部框架会把正确的动画肘角施加到错误轴上。

令qError=qTarget*inverse(qRel)并选择短弧,按前述轴角公式得到A关节框架中的旋转误差向量e。相对角速度也投到A框架,记为omegaRel=rotate(inverse(qA),omegaB-omegaA)。静态目标的比例阻尼驱动取tauA=Kp*e-Kd*omegaRel;运动目标可对连续目标采样求omegaTarget,改为Kp*e+Kd*(omegaTarget-omegaRel)。Kp单位为牛顿·米/弧度,Kd为牛顿·米·秒/弧度。限位关闭的自由度不接受目标,开放自由度分别夹到资产允许角度,再限制总驱动力矩。

把tauA转到世界后,对B施加正扭矩、A施加相反扭矩,步长dt对应角冲量tau*dt。这些冲量与接触、关节位置约束在同一物理步求解,主角色胶囊保持停用;动画只提供目标。若直接给B施加扭矩而遗漏A的反作用,内部起身动作会凭空改变整个人的角动量。目标误差大、力矩已饱和时允许跟随滞后,不能随后把刚体瞬移到动画位置。

驱动权重从零升高时同时缩放刚度和最大力矩,并保留阻尼;刚度很大而物理步过长会造成过冲,使用子步或宿主的隐式驱动求解。连续一段时间骨盆、关节误差和速度都低于阈值后,重新验证主胶囊空间,才在一个写入阶段停用肢体权威碰撞并启用胶囊。空间检查失败就继续由物理驱动维持姿态或回到倒地,避免手臂尚撑在墙上时强行切换。

控制权切换与恢复门禁

从动画进入物理在同一个物理写入阶段提交:先冻结当前动画姿态与前次连续采样,更新所有运动学刚体到相应质心姿态,设置关节锚点、继承速度和碰撞过滤,最后同时启用动态状态并停用主角色胶囊。若某个肢体初始化失败,整次切换保留动画控制;部分骨骼已动态、部分仍由动画直接写入,会让关节连续修正两套目标。

以骨盆高度和速度判断平稳时,同时要求持续窗口,例如0.5秒内骨盆速度小于0.1米/秒、角速度小于0.2弧度/秒,且没有持续外力事件,再提出恢复候选。阈值是起身策略,不能代替胶囊落点检查。将资产标定的胸部朝外轴变到世界,和Up点积大于0.2选择仰卧,小于−0.2选择俯卧;接近侧卧的中间区保持当前候选并等待,避免连续切换起身动作。

恢复落点确定后先以目标胶囊查询空间,结果有效才开始过渡。纯表现路线将肢体碰撞切为不参与角色阻挡的运动学表示,启用角色胶囊;动画插值只写渲染骨骼。过渡中被推入墙或再次受到打击时,取消起身动作,按当前显示骨骼重建全部刚体姿态和连续速度样本,再统一切回物理。完成过渡后释放捕获姿态,控制权交给动画;失败或取消也必须使肢体与胶囊只有一套权威阻挡表示。

验证方法

在跑步、旋转、跳跃和传送后切入,比较切换前后碰撞体位置、质心速度及角速度。切回时检查骨盆、脚底和附着物是否连续。分别关闭相邻自碰撞、修改质量比例与关节限位定位爆炸;性能记录活动刚体数、接触数和约束迭代。

实现与证据

正文为变换与速度推导、引擎接入伪代码。已核对PhysX关节的双局部参考系与弧度约定;尚未建立Ragdoll资产或运行切换场景,动画和物理混合效果待引擎验收。

相关主题

参考资料

  • PhysX5.4.1 Joints:Joint Basics与D6 Joint:双局部约束参考系、角度及驱动;2026-10-22核读。