关于 web3d-animation
web3d-animation 面向设计和实现 three.js 动画场景的团队,通过共享的动画片段规范衔接资产与运行时。它涵盖动画技术选择、骨架与导出检查,以及播放模式。
主要功能
- 01按对象类型选择运动技术
- 02统一动画片段名称和循环规则
- 03检查骨架、导出结果和动画许可
- 04实现混合器、过渡和根运动
- 05规划动画验证与减少动态效果
适用场景
- 01协调角色动画片段与运行时播放
- 02诊断脚部滑动或姿势跳回绑定姿势
- 03准备并验证 glTF 动画资源
- 04优化大量角色的动画处理
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ ssheleg/ web3d-dev --skill web3d-animation安装后在 Claude Code 中输入/web3d-animation确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/asset-animation.mdclip-canon.mdruntime-patterns.md详细介绍
web3d-animation — 决定如何运动,再让两端达成一致
动画场景会在两个素未谋面的人之间的接缝处出问题:一个制作片段,另一个播放片段。片段名为 Armature|mixamo.com|Layer0,代码却请求 run,角色原地滑动,死亡姿势又突然跳回 T 姿势。此技能就是跨越这道接缝的契约——资产端和运行时端,以及它们共同遵循的规范(references/clip-canon.md)。
首要行动 — 先检查,再汇报
- 版本。 在
package.json中读取three。此处的所有 API 信息均已针对 [email protected] 验证;如果版本较旧,先查看references/runtime-patterns.md→ 版本说明,再采信相关名称。 - 哪些东西在运动。 列出每个运动对象及其当前驱动方式:动画片段、代码、着色器、物理,还是尚无驱动。
- 现有资源。 对每个
.glb/.gltf文件运行:npx @gltf-transform/cli inspect <file>— 检查动画(名称、时长、通道)、蒙皮(关节数)、形态目标,以及文件是否经过压缩。将动画片段名称与规范进行比对。 - 资源来源。 如果本会话中有 Asset Foundry 工具(
foundry_capabilities)或asset-foundry技能 → 通过它下单;否则由web3d-assets决定来源。
汇报一张表——对象 · 当前技术 · 所需技术 · 差距——并且只给出一个下一步行动。能检测到的,就不要提问。
第 1 步 — 先选择技术,再处理资源
| 运动对象 | 技术 | 选择此方案而非下一行方案的原因 |
|---|---|---|
| 刚体对象:门、道具、摄像机、3D UI | 在帧循环中变换,或使用制作好的关键帧动画片段 | 为刚体添加骨架纯属额外开销 |
| 环境表面运动:树叶、布料摆动、水流、脉冲 | 在材质上使用 TSL:time、positionLocal.add(offset) | 仅使用 GPU,无需为每个实例使用 CPU |
| 面部、混合变形、修正形状 | 形态目标 | 蒙皮无法表现微笑 |
| 带有制作好的动作的角色 | 通过 AnimationMixer 使用 SkinnedMesh + 动画片段 | 标准路径;以下方案都是对它的优化 |
| 多个副本,姿势相同 | 蒙皮实例化,所有实例共用一次 mixer 更新 | 一次骨架计算即可驱动每个实例 |
| 多个副本,时间各异 | 每个实例调用 mixer.setTime + 一次计算蒙皮处理 | CPU 开销随实例数增长——先测量,然后就此打住 |
| 数千个、无需交互、动作固定的对象 | 在 TSL 中使用顶点动画纹理(VAT) | 运行时无需骨架;three.js 未内置此功能——需要自行实现 |
| 对力作出反应:摔倒、撞击、布娃娃 | 固定步长的物理模拟 | 制作好的动画片段无法响应 |
| 粒子、群集、模拟 | 计算(web3d-runtime) | 根本不属于动画数据 |
BatchedMesh 无法蒙皮。 将道具合批,绝不要将角色合批。
步骤 2 — 资产部分
逐个角色核对这份清单;每一项都是检查项,不是建议。
- 骨架绑定。 采用 T 字姿势或 A 字姿势,单位为米,+Y 朝上,朝向 +Z。自动绑定服务支持人形角色;非人形角色最多只能获得移动动画——应在步骤 1 中决定为其采用程序化动画、形变动画还是 VAT,而不是订购无法制作的骨架绑定。
- 规范。 每个动画片段都应根据
references/clip-canon.md设置规范名称、循环模式和位移规则。导入时一次性映射提供方名称。 - 来源。 如果有 Asset Foundry,则通过它订购(先检查骨架绑定是否可行——检查骨架绑定的成本比给球体绑定骨架低);否则遵循
references/asset-animation.md中的提供方表和许可规则。动作数据许可与网格许可不同——两者都要记录。 - 重定向。 对为其他骨架制作的动画片段进行重定向(
references/asset-animation.md→ 重定向),或在运行时使用SkeletonUtils.retargetClip。 - 导出。 使用 GLB、30 fps、原地动画、每个顶点不超过 4 个影响关节(three.js 只读取一组
JOINTS_0/WEIGHTS_0,其余部分会被静默丢弃),并使用稳定的骨骼名称。 - 预算。 根据目标配置(
web3d-assets)核算关节数、影响关节数、动画片段数和文件大小。r186 移除了 uniform 缓冲区的骨骼数量上限,因此预算考虑的是性能,而非硬性限制。 - 门槛。
npx @gltf-transform/cli validate通过;每个动画片段都能在查看器中播放;循环没有接缝;双脚以动画片段预期的速度保持踩地;没有动画片段以绑定姿势结束。未执行的门槛标记为NOT_RUN。
步骤 3 — 运行时部分
- 使用一个时钟。 使用
new Timer()(r186 中的核心功能;Clock已弃用),调用timer.connect(document),避免隐藏标签页恢复时产生巨大的时间增量;每帧调用一次timer.update(),并为混合器使用经过限幅的dt(例如Math.min(dt, 0.1))。物理系统使用自己的固定步长累加器,并由同一个时钟提供数据。 - 帧顺序:
mixer.update(dt)→ 计算通道 → 渲染。计算蒙皮通道会读取混合器刚写入的骨骼矩阵。 - 每个角色根节点使用一个混合器。 副本通过
SkeletonUtils.clone创建——普通的.clone()会让骨架仍绑定到原始对象的骨骼。重定向后的动画片段应在以SkinnedMesh本身为根节点的混合器上播放。 - 过渡。 移动状态之间采用交叉淡入淡出(
crossFadeTo(next, duration, warp));切换步行↔跑步时使用syncWith保持循环相位。单次播放动画使用LoopOnce;在混合器上监听'finished'事件,而不是在动作上监听。death设置clampWhenFinished = true。 - 动画层。 呼吸、瞄准和上半身手势应作为叠加动画片段(
AnimationUtils.makeClipAdditive)应用于基础移动动画,并通过权重控制,而不是设为第二种状态。 - 根运动与滑步。 使用原地动画片段加代码驱动的移动;根据实际速度与动画片段制作时的速度之比驱动
timeScale,否则双脚会滑动。_rm动画片段的髋部平移由代码提取——three.js 不支持根运动。 - 减少屏幕外计算。 对视锥体之外或远处的角色,跳过或降低
mixer.update的更新频率;隐藏标签页的情况已由Timer处理。 - 减少动态效果。 在
prefers-reduced-motion生效时,停止装饰性动态效果(环境循环、镜头漂移、闲置动作),保留传递含义的动作(受击、状态变化)。页面级规则采用sheleg-design的降级为平静效果;3D 场景也应读取同一信号。 - 清理。 调用
stopAllAction、uncacheRoot,然后释放几何体和材质。
每个步骤的代码见 references/runtime-patterns.md。
注意事项——每一项都会悄无声息,直到有人发现
- 已完成的
LoopOnce动作若clampWhenFinished = false,会禁用自身:角色身体会跳回绑定姿势。死亡和最终姿势需要启用钳制。 'finished'和'loop'事件会在混合器上触发,因为它是此处唯一的事件分发器——AnimationAction没有addEventListener,因此在动作上附加监听器会抛出错误。positionNode = …会替换蒙皮、变形和实例化处理之后的位置。positionLocal.add(x)会保留动画;positionGeometry.add(x)则会将其丢弃。- glTF 中的第二组蒙皮权重会被丢弃,而非合并——请重新归一化为 4 个权重。
- drei 的
useAnimations和 R3F 的useFrame会传入来自已弃用Clock的未钳制 delta;切换到后台标签页后,每个角色都会跳动。请在帧回调中进行钳制。 KHR_animation_pointer(从 glTF 动画控制材质或灯光属性)未内置于 GLTFLoader 中——需要单独注册插件。sheleg-design禁止在滚动区段之间交叉淡化。这条规则针对的是页面运动;交叉淡化角色片段才是正确且标准的过渡方式。
缺少某些功能时
- 此主机上完全没有工具 → 编写命令和代码,绝不编造运行结果。未经测量的尺寸、通过结果、帧时间或“完成”都是伪造的证据;将此类检查标记为
NOT_RUN,并说明需要由人工运行什么。 - 此主机上没有浏览器或无头 GPU → 实现并验证结构,然后将视觉检查项标记为
NOT_RUN,并说明需要人工查看什么。绝不要声称仅凭阅读代码就验证了运动效果。 - 无法使用
@gltf-transform/cli(无网络、无 npx) → 读取 glTF JSON(.gltf直接读取;.glb读取块 0)中的animations、skins和targets;说明无法执行哪些检查(验证、压缩感知检查)。 - 没有 Asset Foundry → 通过
web3d-assets手动获取资源;其原则仍然适用。 - 需要操作人员作出决定(超出预算的付费订单、范围不明的许可证)→ 在该处停止并明确指出;不要绕过。
参考资料
| 阅读 | 适用情况 |
|---|---|
references/clip-canon.md | 命名、循环播放或加载任何片段;映射提供方名称——与 web3d-assets 共用的约定 |
references/runtime-patterns.md | 编写循环、混合器、过渡、图层、重定向、人群、形态实例化、VAT、R3F |
references/asset-animation.md | 制作或购买骨架或片段:提供方、骨架检查、动作许可证、重定向流水线、导出和 QA |
运行时(渲染器、TSL、计算、性能)归 web3d-runtime 所有;文件流水线和预算归 web3d-assets 所有。本技能仅负责动作。
触发条件
其他会引导至此处的短语:“blend idle walk run” / “переход между анимациями”,“crowd of characters” / “толпа персонажей”,“morph targets” / “морф-таргеты”。
评论
支持 Markdown