关于 avatar-animations
为 Decentraland 场景创作者提供制作玩家头像动画的技能,指导先检查内置表情和现成动画包,再用 Blender 创建自定义片段,并验证、导出和交接。
主要功能
- 01优先检索内置表情与动画包
- 02提供 Blender 动画制作流程
- 03校验姿势、穿插与动画范围
- 04导出并验证 emote GLB
- 05说明动画文件的场景交接步骤
适用场景
- 01查找适合场景的现成头像动作
- 02为特定道具制作头像动画
- 03排查姿势、地面或穿插问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ decentraland/ sdk-skills --skill avatar-animations安装后在 Claude Code 中输入/avatar-animations确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/animation-catalog.mdavatar-rig.mdblender-emote-patterns.mdembedded-emotes.md详细介绍
编写 Avatar 动画(场景表情动作)
本技能涵盖制作动画文件:在 Blender 中为官方 Decentraland Avatar 骨架摆姿势,将片段导出为 *_emote.glb,进行验证,并交付给场景使用。播放该动画的场景端 API——triggerSceneEmote、stopEmote、AvatarEmoteCommand、AvatarMask 枚举和权限——位于 player-avatar;本技能会链接到该处,而不重复介绍。
规则:编写动画前先查找现有动画
当用户要求制作 Avatar 动画时,按以下顺序逐项检查,遇到合适的选项就停止——编写动画是最后的手段,而不是默认选择:
- 内置表情动作 — 32 个可按名称播放的 ID(
triggerEmote({ predefinedEmote })或AvatarShape.expressionTriggerId),无需下载:挥手、拍手、舞蹈、坐姿(循环播放)、按钮/杠杆/门/宝箱交互、出拳、投掷……目录{baseDir}/references/animation-catalog.md§1 提供动画预览;循环标记和 5 个仅内嵌的 ID 见{baseDir}/references/embedded-emotes.md。 - Avatar Animations 资源包 — 45 个现成的
_emote.glb动画片段(坐在凳子、坐垫、豆袋和矮墙上;下棋;一整套钓鱼动作;搬运、拾取、饮用、制作、浇灌植物、敲打、挥剑、施法、飞行、舞蹈……)。{baseDir}/references/animation-catalog.md§2 列出了每个条目的时长、下载链接和triggerSceneEmote调用方式。获取preview:webp 以确认动作效果。 - 自定义片段 — 仅当以上选项都不合适(或用户明确想要自定义动画)时使用:采用下方的 Blender 工作流。
说明你选择了哪一种,以及原因。内置动画或资源包中的片段通常比手动制作的更自然,而且只需几分钟,而非数小时;若姿势需要配合特定道具或场景几何结构,自定义动画仍是合适的选择。
开始前确认范围:
| 用户需求 | 技能 |
|---|---|
| 任意类型的 Avatar 动画——先查阅目录 | 本技能 → references/animation-catalog.md(先查内置动画,再查资源包),然后使用 player-avatar 播放 |
| 制作目录中没有的全新动画,且动画对象是玩家的 Avatar | 本技能(Blender 工作流) |
播放内置表情动作或已存在的 _emote.glb | player-avatar |
播放烘焙在 .glb 模型/道具中的动画片段 | animations-tweens |
| 制作 NPC 动画 | npcs |
| 以程序方式移动/旋转实体 | animations-tweens(Tween) |
工作流
- 获取骨架 — 使用
Avatar_File.blend,绝不要手动创建骨架。下载链接及骨骼/控制器/属性参考见{baseDir}/references/avatar-rig.md。 - 设置场景 — 将场景帧率设为 30 fps(交付的文件为 24 fps),记录
Starting_Pose的值,并为每个片段创建一个新动作。 - 制作动画 — 仅在 Pose 模式下调整
CTRL_骨骼,并在每个关键帧为你调整过的所有骨骼设置关键帧。 - 制作时验证 — 输出世界坐标位置(检查穿模、地面和动画区域),并为每个关键帧渲染四个角度的画面,生成联系表。
- 导出 — 每个文件只包含一个片段,仅导出骨架,使用
export_def_bones=True和ACTIVE_ACTIONS。 - 验证 GLB — 解析 JSON 区块:1 个动画、0 个网格、63 个节点、每条路径 62 个通道,时长为
(frames − 1) / 30。 - 交付 — 重命名为
*_emote.glb,放入assets/animations/,添加权限,然后播放(参见 player-avatar)。
涵盖每个步骤的现成 bpy 辅助工具——辅助模块、符号检测、渲染/联系表设置、导出调用和 GLB 验证器——都位于 {baseDir}/references/blender-emote-patterns.md。
如何操作 Blender(无头 CLI 与 Blender MCP、二进制文件路径,以及绝不能悄悄从 MCP 切换到无头模式的规则)已在 {baseDir}/../add-3d-models/references/blender-authoring.md 中说明。表情动作制作完全使用这两种方式;不要重新推导这些内容。
规则:每个片段创建一个新动作,并重置到待机姿势,而不是初始姿势
每个片段都创建一个新动作。在 Blender 4.4+/5 中,动作采用槽位机制,且 Action.fcurves 已不存在(曲线位于 act.layers[0].strips[0].channelbags 下):
act = bpy.data.actions.new(name)
slot = act.slots.new('OBJECT', 'Avatar_Animation')
arm.animation_data.action = act
arm.animation_data.action_slot = slot
开始制作前,先调用 scene.frame_set(0),评估 Starting_Pose,并捕获每根姿势骨骼的变换。这个快照才是关键帧之间重置时的基准,而不是初始变换。骨架的静止姿势是 A/T 姿势;运行时混合所依据的待机姿势则是 Starting_Pose。重置为初始变换会让片段在第一帧突然跳到 T 姿势。
规则:每根摆过姿势的骨骼,都要在每个关键帧为其所有通道设关键帧
scene.frame_set() 会重新评估活动动作,并覆盖所有未设关键帧的姿势(view_layer.update() 不会)。因此,如果某个姿势忘了设关键帧,frame_set 之后进行的渲染会悄无声息地显示待机姿势——你会排查错问题。所以,对每根你调整过的控制骨骼,都要为位置、旋转和缩放插入关键帧;你更改过的任何自定义属性也要插入关键帧:
pb.keyframe_insert('["FK > IK Leg L"]', frame=f)
在第一帧和最后一帧,还要为每根变形骨骼的所有位置、旋转和缩放通道插入关键帧。缺少边界关键帧的通道会保持“开放”状态,保留之前播放的表情动画在该通道留下的值——官方文档称之为表情覆盖,表现为头像的腿仍在执行上一个表情动画。
规则:上臂——用世界轴控制方向,用局部 Y 轴控制扭转
上臂骨骼的局部 X 轴是倾斜的。绕它旋转会让手臂扫过胸前,原本应该双臂向前的姿势最终会变成双臂交叉——这种情况确实会发生,而且从正面渲染图中不容易看出来。因此,应使用世界轴设置手臂的方向,并先将世界轴转换到骨骼当前的坐标系中:
M = (arm.matrix_world @ pb.matrix).to_3x3().normalized()
local_axis = M.inverted() @ Vector(world_axis)
pb.rotation_quaternion @= Quaternion(local_axis, math.radians(deg))
- 纯粹向前抬起 → 世界 X 轴。
- 将抬起的手臂向内或向外移动 → 绕世界 Z 轴偏航。
不过,仅用世界轴无法得到完美的手臂姿势。手臂可以朝很多方向移动,绑定动画的设计师会结合使用世界和局部旋转。以下两种情况需要使用骨骼的局部轴:
- 扭转——手掌朝上或朝下、肘部朝外或朝内,以及需要朝向道具的手腕——只能通过绕骨骼自身长度方向旋转实现;在这个绑定中,该方向是局部 Y 轴(已验证:
CTRL_FK_Avatar_Arm.*的局部 Y 轴就是骨骼轴;旋转它不会移动肘部,只会转动前臂和手)。rl('CTRL_FK_Avatar_Arm.L', 'Y', deg)。 - 微调——当大致方向正确后,进行小幅局部修正通常比再做一次世界轴旋转更精确。
肘部、膝盖、手腕和手指都绕各自的局部 X 轴弯曲(这些控制项的 Y/Z 轴已锁定)——在这些位置使用 rl() 是正确的。
规则:腿部镜像,上半身不镜像——翻转 X 和 Z,修正粘贴后的上半身
Blender 的姿势 ▸ 复制姿势 / 粘贴 X 翻转只适用于这个绑定的一半部分(已在 Avatar_File.blend 上验证;数值见 {baseDir}/references/avatar-rig.md):
- 腿和脚可正常镜像,无论使用 FK 还是 IK——对于 IK 腿,粘贴 X 翻转的结果完全准确;对于 FK 腿,误差在约 3 cm 以内。
- 肩膀、上臂、前臂、手和手指无法正常镜像——粘贴 X 翻转会让另一只手偏离 40–70 cm。绑定动画的设计师采用的修正方法是:对粘贴后的每个上半身控制项,将 X 和 Z 值取反,保留 Y。例如,粘贴后的手臂数值为 X −0.5、Z 0.1,则应改为 X 0.5、Z −0.1。旋转(四元数或欧拉角)需要应用此修正;对于 IK 手部和肘部控制项,位置也要应用此修正。已验证整个手臂链(FK 和 IK)以及全部 30 个手指控制项均完全准确(0.000 m)。
{baseDir}/references/blender-emote-patterns.md中的mirror_side('L')会一次性为每个控制项完成这两个步骤。- 如果只摆一个关节而不是进行镜像,仍需通过程序检测旋转方向的符号:旋转 +15°,测量下游骨骼的移动方向,然后缓存(
auto_sign)。在.L和.R上使用相同角度并不会得到对称姿势。
规则:FK 还是 IK——失去接触时用 FK,保持接触时用 IK
腿部默认为 IK,手臂默认为 FK(CTRL_Avatar_UpperBody 上的 FK > IK * 属性)。仅在姿势需要时切换,并遵循一条规则:如果手或脚需要与地面、座椅、墙壁或道具保持接触,就应使用 IK;如果失去接触,就应使用 FK。
- FK 腿部:跳跃、翻滚、飞行、倒立、游泳,以及双腿悬在平台边缘或剧院座椅外。
- IK 手部:俯卧撑、攀爬、倚靠桌子,以及双手固定在同一道具上。
- 不要在步行循环、舞蹈或仅短暂失去接触的任何动作中切换模式——默认设置足以应对这些情况,而且除非两条链在该帧完全匹配,否则每次切换都会造成跳变。
- 更改时要为
FK > IK属性本身添加关键帧,而不只是为骨骼添加关键帧。
坐姿。 使用 CTRL_Avatar_UpperBody 降低身体——它是重心,会带动整个身体移动。CTRL_Avatar_Hips 只移动骨盆和腿部,会拉伸躯干——坐姿不应使用它。然后分别决定每条腿的模式:
| 脚部位置 | 腿部模式 |
|---|---|
| 双脚着地(椅子、长凳) | 保持 IK:将 CTRL_IK_Foot.* 移至脚要落的位置,然后降低重心——膝盖会自行弯曲,双脚保持着地(已验证:下降 0.4 m 时,脚趾的 Z 值始终为 0)。使用 CTRL_Avatar_Knee.* 调整膝盖朝向。 |
| 一条腿交叉搭在另一条腿上 | 仅将抬起的那条腿切换为 FK;着地的腿保持 IK。 |
| 双脚离地(池塘边、剧院座椅、高脚凳) | 双腿都使用 FK。 |
setprop('CTRL_Avatar_UpperBody', 'FK > IK Leg L', 0.0) # only for a leg that leaves the ground
setprop('CTRL_Avatar_UpperBody', 'FK > IK Leg R', 0.0)
# ...then pose CTRL_FK_Avatar_UpLeg / _Leg / _Foot / _ToeBase on that side
无论使用哪种模式,都要检查双脚:Avatar_LeftToeBase / Avatar_RightToeBase 的世界 Z 坐标必须保持 ≥ 0,否则 Avatar 会陷入地面。
规则:渲染之外,也要用数值验证
渲染可以检查构图,数值可以检查穿模。打印每个关键帧中双手、头部、双脚以及任何道具参考点的世界坐标:
- 肢体经过头部时,双手与头部中心的距离至少保持在 约 0.3 m。手臂先朝外绕行之前,向肩后投掷的动作会直接穿过头骨。
- 双手之间至少保持 约 0.10 m 的距离,避免在中心线处重叠。
- 在任何默认姿势或保持姿势中,都要让面部保持可见——将物体举至胸口上部高度并低头看向物体,不要把物体挡在脸前。
每个关键帧都用 Workbench 渲染四个角度(正面四分之三视角、正面视角、侧面视角、俯视),并将其平铺到一张联系表中。先在低成本的纯姿势阶段迭代(每次运行只需几秒),然后再进行包含导出的完整构建。
规则:动作必须保持在动画区域内
根据 Avatar_File.blend 中的参考对象测量(单位为世界米,Blender 使用 Z 轴向上):
| 参考对象 | 范围 | 含义 |
|---|---|---|
Animation_Area_Reference | 4 × 4 × 4 m 盒体 — X、Y ∈ [−2, 2],Z ∈ [0, 4] | 整个片段期间,所有内容都必须保持在盒体内:每个身体部位、道具和粒子都不能例外。任何内容都不能沿任意方向移动超过 4 m。 |
Root_Animation_Area | 位于原点、直径为 2 m 的圆柱体 | Avatar 的根节点/重心(CTRL_Avatar_UpperBody,即 Avatar_Hips)向前、后、左或右移动最多 1 m,横向总跨度为 2 m。垂直方向可升至盒体允许的最高处(文档称为 4 m;文件中的圆柱体网格高 3 m)。 |
Ground_Reference | 位于 Z = 0 的平面 | 任何内容都不能低于该平面。 |
在此范围内,片段可以包含根节点平移——整个身体向前行走、向一侧塌倒或下沉穿过地面——Explorer 会在玩家和 AvatarShape NPC 上重放此平移(游戏内观察结果,Unity Explorer v0.186.0-alpha,SDK 7.30.1,2026-10-10)。这是全身表情播放期间移动 NPC 的唯一方法,因为使用 Transform/Tween 移动会取消表情(npcs)。
腿、手臂、头部和道具可以超出根节点圆柱体——踢腿或侧手翻就是如此——但必须保持在盒体内。将以下检查加入逐关键帧报告:|hips.x| ≤ 1、|hips.y| ≤ 1,每根变形骨骼的头部和尾部都在盒体内,每个脚趾的 Z ≥ 0({baseDir}/references/blender-emote-patterns.md 中的 in_area())。Decentraland Tools 插件的Validate Emote 只会在 CTRL_Avatar_UpperBody 相对首帧水平或垂直移动超过 1 m 时发出警告;它不会检查盒体,因此需要自行运行 in_area() 检查。
规则:循环必须闭合;单次播放动作必须落在场景恢复时的姿势上
- 循环片段:确保第一帧和最后一帧完全相同(例如,4 s 循环的第 1 帧和第 121 帧),否则循环处会跳变。
- 单次播放片段:起始和结束姿势都要与场景恢复时的静止姿势一致——对于坐姿游戏,使用坐姿持物姿势;否则使用
Starting_Pose。
规则:每个文件只导出一个片段,且仅包含骨架
先删除所有其他对象——网格、WGT_* 控件、参考平面、Armature_Prop、摄像机、灯光——并移除 Starting_Pose 动作,否则导出器会输出两个片段。export_animation_mode='ACTIVE_ACTIONS' 可确保每个文件恰好包含一个动画。完整的导出调用见 {baseDir}/references/blender-emote-patterns.md。
在剥离内容之前,先保存可编辑的 .blend 文件(包含网格),这样用户之后可以手动调整动作。
规则:交付前验证导出的 GLB
解析 GLB 的 JSON 区块并断言:1 个动画、0 个网格、63 个节点(Armature + 62 根变形骨骼)、1 个蒙皮,平移/旋转/缩放各有 62 个通道,且 duration == (last_frame − first_frame) / 30。验证脚本见 {baseDir}/references/blender-emote-patterns.md。时长不匹配意味着场景 FPS 不是 30。
使用 export_frame_step=1 时,1–4 s 片段的典型大小为 70–110 KB——远低于 3 MB 上限,因此通常没有理由增大采样步长。
上半身(蒙版)动画
蒙版表情并不是另一种文件格式——触发时,播放的仍是同一个 .glb,但会设置 mask: AvatarMask.AM_UPPER_BODY(API 和枚举详情:player-avatar →“表情蒙版”)。改变的是你应该创作的内容。
蒙版保留的骨骼——已对照 Explorer 的 UpperBodyAvatarMask.mask 资源验证:
- 动画骨骼:
Avatar_Spine、_Spine1、_Spine2、两侧肩膀/手臂/前臂/手、全部 40 根手指骨骼、Avatar_Neck、Avatar_Head。 - 忽略的骨骼:
Avatar_Hips和两条腿(UpLeg/Leg/Foot/ToeBase)——这些骨骼会保留该帧中 locomotion 状态或其他表情的动作。
渲染器的工作机制是:每次 LateUpdate 对你的动画片段进行采样,然后从 Animator 已生成的姿势中恢复未被蒙版覆盖的骨骼的局部位置和旋转(MaskedLegacyEmoteBlender)。因此:
- 蒙版动画片段中的髋部/根运动不起作用。
Avatar_Hips不在蒙版范围内,因此你用CTRL_Avatar_UpperBody制作的坐下动作会被丢弃;腿部会显示 locomotion 状态(待机、行走、跑步)。 - **蒙版动画片段不会叠加到其他表情上。**已在 Explorer 的
SceneMaskedEmoteSystem中验证:为本地玩家启动蒙版表情时,任何正在播放的全身表情都会停止;启动全身表情时,蒙版表情会被取消。因此,蒙版动画片段不能叠加在椅子的坐姿表情上——角色会站起来。它只会叠加在 locomotion 上,这正是蒙版的用途:让玩家在行走、跑步或待机时也能搬运、持物或欢呼。 - 对于坐着的玩家,先检查
sittingChair1/sittingGround1——它们会循环播放并免费保持姿势(参见本技能顶部关于嵌入式表情的说明)。如果你确实要创作一个动画片段,发布前让负责人检查手臂和双手:2026-10-12 的观察显示,下面的 IK 脚部 + 降低UpperBody方案虽然生成了正确的坐姿,但手臂姿势很别扭,只有人眼才能发现。 - **对于坐着的玩家,应全身播放动画片段。**在每个动画片段中创作坐姿下半身(降低髋部,FK 腿部弯曲),不使用蒙版触发;动画片段结束且没有循环坐姿动画片段接替时,让场景重新播放坐姿表情(
triggerEmote({ predefinedEmote: 'sittingChair1' })或椅子自身的表情)。如果一次性动画片段返回到循环待机动画片段的同一坐姿,就能无缝衔接;唯一明显的跳变是与内置坐姿表情之间的高度差,可以通过调整髋部下沉幅度来控制。 - **即使供蒙版使用,也要创作完整的全身动作。**合理的下半身动作能让同一文件也可在不使用蒙版时播放。蒙版是在触发时决定的,而不是文件本身的属性。
- 本地玩家的蒙版表情不会发出
AvatarEmoteCommand生命周期事件(见 player-avatar 文档)。因此,场景必须自行计时——在场景配置中,将每个动画片段的时长与其路径一同保存,因为你可以通过帧数准确获知时长。
坐姿持物姿势的设计要点:髋部约为 0.6 m,双手置于胸部高度,头部朝双手方向倾斜。
上述骨骼列表和混合机制来自 Explorer 源码(
main分支上的MaskedLegacyEmoteBlender、SceneMaskedEmoteSystem、CharacterEmoteSystem,2026-09);“蒙版表情会停止全身表情”这一规则已在实际场景中对坐着的玩家进行了确认。对于枚举值和调用签名,请以 player-avatar 为准,该文档已根据发布的协议验证。
文件要求
| 要求 | 值 | 来源 |
|---|---|---|
| 帧率 | 30 fps(Blender 默认为 24) | 文档 |
| 最长时长 | 10 s / 300 帧 | 文档 |
| 格式 | .glb | 文档 |
| 最大文件大小 | 3 MB | 文档 |
| 采样率 | 默认为 1;设为 2 或 3 可缩小文件 | 文档 |
| 每个文件的动画片段数 | 恰好 1 个(Emotes 2.0 可能会添加 1 个道具片段;不支持序列) | 文档 |
| 文件内容 | 仅限变形骨架 + 动画——不能包含网格、控制骨骼、摄像机或灯光 | 文档 |
| 起始 / 结束姿势 | 两者都使用静止姿势(Starting_Pose) | 文档 |
| 变形骨骼关键帧 | 每根骨骼在第一帧和最后一帧都要设置位置 + 旋转 + 缩放 | 文档 |
| 动画区域 | 根节点在每个水平方向上的移动距离 ≤ 1 m(总宽度 2 m);每个网格部件和道具都必须位于 4 × 4 × 4 m 的 Animation_Area_Reference 盒内(见上方规则) | 文档 + 测量 |
| 文件名 | 必须以 _emote.glb 结尾(不区分大小写) | player-avatar |
| 场景权限 | 在 scene.json 的 requiredPermissions 中添加 ALLOW_TO_TRIGGER_AVATAR_EMOTE | player-avatar |
场景中的常见存放位置:assets/animations/。glTF 动画的名称对运行时无关紧要——文件路径才是标识符。
如果用户要手动导出,Blender 的 glTF 导出器 UI 中对应的选项为:Include > Limit to > Visible Objects、Data > Armature > Export Deformation Bones Only、Animation > Sampling Animations。
Decentraland Tools 插件的 Validate Emote 操作会在导出前检查其中大部分要求(30 fps、≤ 300 帧、恰好一个骨架动作、变形通道在第一帧和最后一帧均设有关键帧);如果 COG 水平或垂直移动超过 1 m,则会发出警告,但不会阻止导出。它不会检查 4 m 边界框。
在场景中测试
最快的测试工具是一排可点击的基本几何体立方体——每个动画片段对应一个,使用 MeshRenderer + MeshCollider + pointerEventsSystem.onPointerDown,并设置较大的 maxDistance,确保坐在椅子上也能点击;再加上一个 Stop 立方体和一个遮罩切换立方体:
pointerEventsSystem.onPointerDown(
{ entity: cube, opts: { button: InputAction.IA_POINTER, hoverText: label, maxDistance } },
() => void triggerSceneEmote({ src, loop: false, mask: upperBody ? AvatarMask.AM_UPPER_BODY : undefined })
)
使用配置标志控制整个测试工具,并在发布前将其移除。
Explorer MCP 的 trigger_emote 只能播放 URN / 基础表情动画,不能播放场景文件——它无法测试 _emote.glb。请使用场景内触发器(参见 unity-explorer-mcp,了解如何驱动客户端在触发器附近移动)。
交叉引用
- player-avatar —
triggerSceneEmote/stopEmote/AvatarEmoteCommand/AvatarMask、_emote.glb规则、权限,以及在全身表情动画期间使用InputModifier冻结玩家。 - add-3d-models →
references/blender-authoring.md— 如何驱动 Blender(无头 CLI 与 MCP),以及通用模型导出规则。 - animations-tweens — 烘焙到道具和模型中的动画,以及程序化
Tween动作。 - npcs — 为
AvatarShapeNPC 和 GLB NPC 制作动画。 - 官方文档:创建表情动画 · 骨架功能 · Avatar 骨架