Skip to content

当动画必须与世界发生接触 ​

作者:Oleg Sidorkin,Cinevva 首席技术官兼联合创始人

行走动画知道腿该如何运动,却不知道一只脚已经踩上台阶。伸手动画知道手臂该如何运动,却不知道这个锁孔具体在哪里,也不知道有人移动了杯子。

这是自动绑定角色之后的下一个问题:让动画在游戏运行期间对场景作出响应。我们已在 Cinevva 的 Three.js 运行时中实现了一个实验性校正层。它会读取动画生成的姿势、查询场景,并在渲染当前帧之前调整角色的关节。

下面的示例会直接在你的浏览器中运行这套代码。逐帧循环中不会发起任何动作生成请求。

亲自体验差异 ​

演示会自动开始。选择一个示例,然后关闭或开启校正。左侧角色显示基础姿势,右侧角色则会接受实时校正。你可以暂停并拖动时间轴,检查某个特定时刻。拖动任一视口可绕角色旋转视角,滚动或双指捏合可缩放,按住右键拖动可平移。两个摄像机始终保持同步,因此你可以从完全相同的角度检查同一处接触。

每个示例都使用同一个由 Cinevva 自动绑定的青蛙角色。行走示例播放的是通用动画库中的 Walk,并通过 Auto Rigger 所用的同一套代码进行重定向。两个视口都会播放实际动画片段;右侧额外加入运行时地形校正。其他示例保留嵌入的 Idle 参考动画及各自的交互控制器。

行走控制器会提前规划一个步幅。它预测脚落地时移动踏板的位置,将青蛙的整个脚掌置于落脚区域中央,并使即将摆动的脚越过未来台阶的高度。它在调整步幅长度的同时,保留动画库片段原有的节奏和摆腿形态。骨盆会在落地前开始转移重心并改变高度;随后,IK 将四肢放到规划好的目标位置,并细化可见的脚掌接触效果。

开启脚步规划后,可以看到预测落脚位置处的脚掌轮廓和虚线摆动路径。骨盆轨迹用于比较身体运动,而保存骨盆轨迹会保留测量结果。此规划器目前可以处理演示中已知的平移踏板。它会报告无法实现的落脚;任意地形导航和物理平衡力则属于独立的引擎职责。

攀爬梯子会每次移动一个肢体,同时让另外三个接触点保持在梯级上。梯子会向下移动,让攀爬者始终位于视野中。明确的脚踝和手部目标负责放置接触点,而手肘和膝盖引导目标则确保弯曲部位避开梯子。身体运动和接触顺序均由人工编排;这并不是自动攀爬规划器。

已实现的功能 ​

能力运行时目前的行为
不平整地面查询每只脚的支撑点,对齐其经过校准的脚掌法线,并调整骨盆高度。
脚部固定相对于支撑脚部的表面保持站立接触。
移动平台让接触点跟随平移或旋转的支撑物运动。
手部目标通过混合权重,让手臂朝向世界空间中的位置和朝向进行求解。
手持物体根据期望的物体姿势和固定握持变换推导手腕目标。
无法触及限制求解范围,并报告需要重新定位角色。

这是一个可选择启用的运行时原型。交互示例展示了当前实现,但并不意味着每个由 Cinevva 生成的游戏都会自动启用它。

固定的脚需要参考坐标系 ​

我们现有的重定向器在把动画片段转移到身体比例不同的角色上时,已经可以校正一部分脚部漂移。运行时贴地还有另一个输入:角色此刻所站立的表面。

当一只脚进入支撑阶段时,新校正层会在支撑物体的局部坐标中记录其接触点。在静止地面上,身体移动时脚会保持原位。在移动平台上,同一个已存储的点会随平台一起移动。如果只把它锚定在世界坐标中,脚就会被留在原处。

随后,骨盆会在双腿都能够触及的有界高度范围内移动,每条腿则朝各自的脚部目标进行求解。一次早期测试发现了一个细微问题:跨越可触及边界对骨盆进行平滑处理时,脚会短暂悬浮在斜坡上。现在,平滑处理会始终限制在可行范围内。

青蛙角色还暴露了另一个校准错误:最低的脚趾接触地面,并不代表整个脚掌已经贴合。演示现在会为每个已摆好姿势的脚部网格拟合支撑平面,同时校准位置和法线。渲染回归测试会在整个 Idle 动画期间测量三个分离的脚掌接触点以及最低表面点。

共享的身体支撑检查通过加权身体分段估算质心,并计入示例性的手持物体负载。站立和伸手示例使用它引导骨盆朝承重脚移动。行走期间,脚步规划器负责预期的重心转移;静态的支撑区域居中校正不得干扰规划好的运动。诊断信息仍会显示估算质心和支撑接触点。行走示例会报告规划的重心转移,梯子示例则会报告握持力尚未经过验证。

行走仍然需要时序信息。游戏会为每只脚提供一个权重,表示此刻应在多大程度上将它视为固定状态。摆动中的脚必须解除固定。游戏还要提供步态、角色移动以及越过下一级台阶所需的净空。这些决策并非由 IK 求解器推断。

先把钥匙放进锁孔,再求解手部姿势 ​

只让手腕对准锁孔是不够的。钥匙有长度、插入轴和握持偏移。即使手腕完美到达目标,钥匙尖端仍可能偏离。

在演示中,交互序列定义了钥匙的期望位置和旋转。握持信息会告诉我们手腕必须位于哪里,才能让钥匙到达相应位置。随后,手臂会朝该手腕姿势进行求解。实际钥匙始终附着在求解后的手部,即使请求的位置无法触及时也是如此。

无法触及的目标示例特意展示了这种失败情况。肢体不会为了让指标看似成功而被拉长;运行时会报告需要重新定位角色。

该示例包含人工编排的靠近、插入和转动阶段。目前,它还不会规划手指抓握,也不会根据锁具内部的净空检查钥匙形状。

倾倒也是朝向问题 ​

倾倒示例会在倾斜容器的同时,让容器出口保持在杯子上方。随着容器旋转,所需的手腕位置也会变化。同一套手部目标机制会跟随这个不断变化的姿势。

蓝色液流是在倾斜期间启用的视觉效果,并非流体模拟。它在这里的作用是直观展示对齐效果:没有校正时,液流会错过杯子;启用校正后,它会落入杯子的承接区域。

校正在何时运行 ​

游戏中的执行顺序为:

移动角色 → 计算动画 → 应用姿势偏移 → 求解场景接触 → 更新次级运动 → 渲染。

运行时通过 createAnimator 公开此功能,并接受可选的 sceneIK 配置。游戏会把接触权重、手部目标和贴地状态传入 update。它还可以封装现有的 Three.js 动画混合器。

每套骨骼都需要有意义的脚部和握持校准。骨骼名称映射可以帮助我们找到正确的肢体,但脚踝关节并不是鞋底。此版本为每只脚使用一个经过校准的支撑点;它还没有对完整的脚跟与脚趾支撑区域建模。

底层技术在 Unity 的双骨骼 IK和 Unreal 的 IK 求解器中都有成熟的对应方案。我们的实现是一个围绕自动绑定角色需求构建的小型引擎端校正层。

我们验证了什么,以及还有哪些工作 ​

第一轮验证包括 14 项数值与集成测试,以及在 3,840 帧中采样的八个渲染场景。我们检查了移动支撑、斜坡接触、恒定动画轨道、坐标变换、触及范围限制,以及运行时动画器集成。浏览器自动化还比较了启用和禁用校正时的画布,并测试了窄屏布局。

这些测量会检查肢体与目标之间的误差。它们并不能证明蒙皮网格的每个部位都不会发生碰撞,也不能保证结果在每个角色上看起来都自然。这些示例特意保持了较小的规模,以便与相应数值一起检查。

接下来的工作包括脚步规划、更完善的脚掌支撑、全身触及、手指抓握,以及具备碰撞感知能力的交互阶段。物理模拟液体则又是一个独立系统。

目前,我们已经得到了一个具体而实用的成果:动画可以保留其基础运动,同时让角色的手脚在每一帧中响应场景。这为自动绑定的角色与周围世界进行交互提供了起点。