2D 骨骼
2D 骨骼让一张图像身体一样弯折。任何 PNG 都可以在编辑器里直接做,不需要另外的动画软件,也不依赖第三方格式。 Spine 和 DragonBones 照常可用;角色是用哪个做的,就继续用哪个。
.esrig是你编辑的文件:从图上切出的部件、部件下面的骨骼、每个顶点跟随哪些骨骼。- 保存时在旁边写出
.esmesh和.esprefab。场景只用这两个,所以打包后的游戏不带编辑数据。 - 骨骼就是实体。 每根骨骼都是带 Transform 的普通实体,片段、Animator、遮罩和代码都能像控制其他实体一样控制它。
在内容浏览器里右键一张图,选 创建 2D 骨骼。然后沿顶部的模式依次操作,顺序就是做角色的顺序:
| 模式 | 做什么 |
|---|---|
| 部件 | 按透明区域切分 把一张肢体拼图切成部件,再拖动摆成角色。右侧列表决定谁画在上面。 |
| 骨骼 | 选 新建 后拖出一根骨骼;从另一根骨骼的末端开始,就接在它后面。选 选择 时,拖末端调方向,拖其余位置移动。 |
| 网格 | 每个部件一开始就盖着一层网格。格子越小弯折越顺,代价也越大。拖动顶点可以微调。 |
| 权重 | 按距离 先绑定最近的骨骼,再刷它弄错的地方:在右侧选一根骨骼后拖动。Shift 反向,Ctrl 平滑,[ 和 ] 调半径。整个部件跟选中骨骼 用于不弯的部件。 |
| 变形 | 新建形状,然后拖动把顶点推过去:呼吸、微笑、鼓起。 |
试摆 可以转动骨骼,看权重是否合适。它不改骨骼文件,回到 绑定姿势 就复原。放入场景 会保存并实例化 prefab。再次保存时,打开的场景里所有实例马上更新,实例上后加的内容会保留。
绑定之后重新绑定
Section titled “绑定之后重新绑定”角色不会锁死在最初刷权重的那套骨骼上。
- 挪骨骼。 在 绑定姿势 下拖动骨骼或改长度、旋转,改的就是绑定姿势本身。图不会动,所以放错的骨骼直接挪就行。
- 换父骨骼。 在 骨骼 模式里给选中的骨骼选 父骨骼,或者选 无(根骨骼)。它在图上的位置不变,下面的骨骼也不变。
- 改名、删除。 删除骨骼时,它的子骨骼和顶点交给父骨骼。
- 重算权重。 再点一次 按距离,或 整个部件跟选中骨骼,然后再刷。
- 换成另一个骨骼文件的骨架。 在 骨架 下选另一个
.esrig,点 换绑到这套骨架。骨骼按名字对应;没有同名骨骼的顶点交给最近的同名父骨骼。用同一套骨架的角色骨骼名和路径都一样,可以共用动画。
保存时,依赖旧名字的东西会跟着更新:
- 用路径引用了改名或换父骨骼的动画(
.estimeline)和 Animator 层遮罩(.esanimator)会被改写。一个文件里大部分路径都是这个角色的骨骼,才算这个角色的。指向已删除骨骼的轨道保留原路径,保存时会提示有几条。 - 每根骨骼有一个固定 id,prefab 里的实体就按它命名。所以场景里加在某根骨骼上的东西(
IK2D、挂在手上的剑),在别处重排、换父或删除骨骼之后仍然留在这根骨骼上。
在场景里,选中带 MeshSkin 的实体,在 Details 里用 换绑到:选场景里的另一套骨架,点 按名字换绑关节。每个关节在那套骨架下找同名实体;同一个名字出现两次时(比如两只胳膊下都有 hand),按父级的名字区分。找不到的关节保持原样,并列出名字。3D 蒙皮同样适用,比如把一件外套绑到身体上。
选中角色,在时间线里像其他实体一样给骨骼打关键帧。骨骼按它在根下面的路径命名,比如 hips/spine/arm。变形是 MeshMorph 组件上的权重,打关键帧的方式相同。
混合由 Animator 负责,和其他角色一样:1D、2D 混合、分层、遮罩和过渡都对骨骼有效。
给肢体的最后一根骨骼加 IK2D,把 target 指向一个实体。这根骨骼的末端会在动画播放之后去够它,所以不管播哪个片段,手都能握住要握的东西。
| 字段 | 含义 |
|---|---|
target |
要够到的实体。 |
chainLength |
弯折几根骨骼,包括这一根。两根时精确求解并保持弯折方向;更多时迭代求解。 |
bend |
两根骨骼时中间关节的弯折方向:1 逆时针,-1 顺时针。 |
weight |
从动画姿势向解算结果靠拢的比例。可以打关键帧。 |
matchTargetRotation |
让这根骨骼同时转到目标的旋转,比如脚贴合斜坡。 |
给骨骼加 BoneConstraint2D。约束在 IK 之后运行,从躯干向外:
kind |
作用 |
|---|---|
| Limit Rotation | 把局部旋转限制在 min 和 max 之间。穿过这根骨骼的 IK 链也会遵守。 |
| Copy Rotation | 取 source 的世界旋转,再加 offset。 |
| Copy Position | 站到 source 的世界位置上。 |
| Look At | 让骨骼的 +x 指向 source,再加 offset。 |
IK 和约束在播放模式下运行。根节点用负缩放镜像的角色同样适用。
骨骼是普通数据,游戏或工具都可以自己生成:
import { autoWeightPart, bakeRig, coverRigPart, createRig, rigImageFromRGBA, spawnRig, IK2D,} from 'esengine/rig2d';
const image = rigImageFromRGBA(width, height, rgba);const rig = createRig('hero.png', width, height);rig.bones.push( { name: 'upper', parent: -1, x: 0, y: 0, rotation: 0, length: 50 }, { name: 'lower', parent: 0, x: 50, y: 0, rotation: 0, length: 50 },);const rect = { x: 0, y: 0, w: width, h: height };const part = { name: 'arm', rect, x: 0, y: height / 2, ...coverRigPart(image, rect), weights: [] };rig.parts.push(part);autoWeightPart(rig, part);
const mesh = assets.createMesh(bakeRig(rig));const { bones } = spawnRig(world, rig, { mesh, texture });world.insert(bones[1], IK2D, { target, chainLength: 2, bend: 1, weight: 1, matchTargetRotation: false, enabled: true });- 一个骨骼角色是一个网格、一次绘制,最多 256 根骨骼。一个顶点最多跟随 4 根。
- 同一角色的部件按你设定的顺序绘制。和场景其他内容之间,按
MeshRenderer.layer再按 z 排序,和普通网格一样。 - 选中角色时的外框显示的是绑定姿势,不是当前姿势。