22 KiB
SpineParticle · Spine JSON 导出设计标准规范
文档性质:导出功能开发、验收与后续维护的唯一对齐基线
规范状态:已完成产品规则对齐,导出设置面板已实现,JSON 导出逻辑尚未开始
目标格式:Spine JSON 4.2
主要用途:将导出 JSON 重新导入 Spine 编辑器继续编辑
最后更新:2026-08-31
一、规范目的
本规范用于固定 SpineParticle 的 Spine JSON 导出范围、骨架结构、动画烘焙、资源引用、拖尾蒙皮、关键帧压缩和导出设置语义,避免后续开发因上下文丢失或实现人员变化而偏离已确认规则。
后续实现若与本文冲突,应先重新确认并更新本文,不能仅在代码中改变既定语义。
二、导出目标与边界
2.1 导出目标
导出结果是一个能够由 Spine 4.2 识别,并能重新导入 Spine 编辑器继续编辑的 JSON 骨架动画文件。
导出数据必须满足:
- 粒子表现不依赖 SpineParticle 编辑器运行时;
- 粒子、序列帧、颜色、透明度、缩放、旋转、拖尾等表现被转换为 Spine 原生骨骼、插槽、附件与动画时间轴;
- 与其他场景模块发生关联的粒子表现必须烘焙为独立动画数据;
- 文件结构优先兼顾可编辑性、动画精度和合理体积;
- 导出后使用 Spine 4.2 Runtime 进行结构解析验证。
2.2 导出内容
只导出场景中的粒子系统相关内容:
- 粒子系统骨骼;
- 粒子图片插槽和 Region 附件;
- 粒子位移、旋转、缩放动画;
- 粒子颜色和透明度动画;
- 粒子图片与序列帧附件切换;
- 拖尾骨骼链;
- 拖尾加权 Mesh、颜色、透明度和资源切换;
- 项目中的“所属动画”及其粒子时间轴。
2.3 不导出的内容
以下场景对象本身不进入 JSON:
- 碰撞体;
- 路径;
- 已加载的 Spine 对象;
- 原 Spine 对象中的骨骼、插槽、皮肤、图片和动画;
- 编辑器辅助线、网格、背景图、骨骼预览点和调试显示。
这些模块若影响了粒子运动,必须只烘焙其最终结果,不能在导出 JSON 中保留对原对象的引用。
2.4 场景显隐规则
- 场景对象小眼睛关闭的粒子系统不导出;
- 显示状态正常的粒子系统参与导出;
- 碰撞、路径和 Spine 对象无论是否显示都不作为对象导出;
- 若可见粒子系统的模拟依赖有效的碰撞、路径或 Spine 跟随,其最终影响仍应被烘焙。
三、格式依据与版本规则
3.1 格式依据
实现时依次以以下内容作为格式依据:
- Spine 官方 GitHub 仓库中的 Spine 4.2 JSON 示例;
- 项目当前使用的
@esotericsoftware/spine-core 4.2.119JSON 解析器; - 项目已有的 Spine 4.2 官方导出样本;
- Spine 官方 JSON 格式说明。
官方中文说明中的部分示例仍使用 Spine 3.8,不能直接照搬旧版字段。实现必须重点核对 Spine 4.2 的:
skins结构;rgba插槽时间轴;attachments动画结构;- 加权 Mesh 顶点编码;
- 附件切换;
- 多动画结构;
- Draw Order 字段命名;
- Sequence 附件及时间轴结构。
3.2 版本范围
第一版只支持:
Spine 4.2
设置面板保留下拉框,以便以后扩展版本,但第一版不得提供没有真实兼容实现的 4.0、4.1 或其他版本选项。
四、整体 JSON 结构
导出 JSON 的主要结构为:
skeleton
bones
slots
skins
animations
不输出无关约束、碰撞体或路径附件。
推荐骨架层级:
root
├─ ParticleSystem1
│ ├─ _particle_000
│ ├─ _particle_001
│ ├─ _particle_000_trail_1_0
│ │ └─ _particle_000_trail_1_1
│ │ └─ ...
│ └─ ...
└─ ...
每个粒子系统必须作为 root 下的独立父骨骼,粒子骨骼统一使用简洁的 _particle_000 样式并归入对应系统。所有骨骼、插槽和附件名称仍须全局唯一;多系统发生重名时只为后续同名骨骼追加最短编号后缀。
五、Setup Pose 标准
5.1 普通骨骼
除拖尾子骨骼链外,所有导出骨骼的 Setup Pose 使用统一默认值:
x = 0
y = 0
rotation = 0
scaleX = 1
scaleY = 1
粒子系统在编辑器中的位置、旋转和缩放不写入普通骨骼 Setup Pose,必须进入对应动画时间轴。
5.2 拖尾骨骼链例外
拖尾是加权 Mesh 的绑定骨骼链。为了保证导入 Spine 后初始蒙皮结构正确:
- 拖尾链保持正常父子层级;
- 子骨骼保留合理的绑定位置和骨骼长度;
- 子骨骼不能全部重叠在原点;
- 动画帧中的拖尾世界状态转换为相对父骨骼的局部位移和局部旋转;
- 拖尾链根独立于粒子图片骨骼的旋转和缩放,避免粒子图片变换意外污染拖尾蒙皮。
5.3 Setup Pose 可见性
所有蒙皮绑定完成后的粒子 Region 和拖尾 Mesh 在 Setup Pose 中默认透明度为 0,避免导入 Spine 后干扰已有图像显示。
动画开始后,由附件切换和 rgba 时间轴恢复正确图片、颜色与透明度。
六、粒子到 Spine 数据的映射
| SpineParticle 数据 | Spine 4.2 数据 |
|---|---|
| 粒子系统 | 系统根骨骼 |
| 粒子池槽位或独立出生粒子 | 粒子骨骼 |
| 粒子图片 | Region 附件 |
| 粒子图片显示层 | Slot |
| 粒子位置 | Bone Translate Timeline |
| 粒子旋转 | Bone Rotate Timeline |
| 粒子缩放 | Bone Scale Timeline |
| 粒子颜色与透明度 | Slot RGBA Timeline |
| 粒子出生、死亡、假死 | Attachment 与 RGBA Timeline |
| 多图片资源 | 同一 Slot 下的多个 Region 附件 |
| 序列帧 | Attachment Timeline 切换 Region |
| 混合模式 | Slot Blend |
| 拖尾 | 加权 Mesh + 拖尾骨骼链 |
| 拖尾颜色与透明度 | 拖尾 Slot RGBA Timeline |
| 所属动画 | animations 下的动画名称 |
七、粒子骨骼与对象池
7.1 开启骨骼对象池
开启时:
- 按粒子系统最大同时存活数量建立固定粒子骨骼池;
- 粒子死亡后骨骼可供后续粒子复用;
- 图片 Slot 和对应拖尾骨骼链随粒子骨骼一起复用;
- 文件骨骼数量和时间轴体积应显著小于不复用模式;
- 复用前后通过 Attachment 和 RGBA 关键帧明确隐藏、显示及切换资源。
7.2 关闭骨骼对象池
关闭时:
- 每一次逻辑粒子出生建立独立骨骼;
- 已死亡粒子的骨骼不再分配给后续粒子;
- 动画较长或发射率较高时允许产生大量骨骼;
- 界面无需阻止,但导出前可以提示预计骨骼数量和文件体积。
7.3 循环动画例外
纯循环持续动画必须保证循环衔接帧两端的粒子身份稳定。即使关闭对象池,也必须为跨越循环接缝的粒子维持稳定骨骼映射,避免循环首尾出现身份跳变。
八、图片与序列帧
8.1 图片文件
导出功能不复制、不下载、不嵌入 PNG,也不生成 Atlas。
JSON 只负责输出正确的图片资源路径。用户将在 Spine 中重新扫描并指定图片文件夹。
禁止把以下编辑器内部地址写入附件路径:
- Data URL;
- Blob URL;
- 浏览器临时对象地址;
- 本机绝对文件路径。
8.2 图片路径
设置中的图片路径,例如:
./images/
写入 skeleton.images。
附件 path 只写相对于图片文件夹的资源路径,不重复附加 ./images/。附件路径应:
- 保留资源子文件夹结构;
- 统一使用
/; - 清理重复的
./; - 使用稳定文件名;
- 默认使用不含图片扩展名的 Spine 资源路径;
- 检测并提示重复路径。
8.3 图片缺失
图片缺失不阻止导出。
- 仍然输出对应 Region 或 Mesh 附件;
- 保留用户可识别的文件名和路径;
- Spine 中允许显示缺失图片,用户可根据文件名补充文件;
- 能取得图片原始尺寸时写入真实尺寸;
- 完全无法取得尺寸时写入安全占位尺寸并给出提示;
- 缺图、路径重复或占位尺寸属于警告,不直接取消 JSON 下载。
8.4 图片尺寸、缩放和锚点
- Region
width/height使用图片原始像素尺寸; - 粒子资源缩放已经体现在粒子骨骼 Scale 动画中,不得重复乘到图片尺寸;
- Pixi 锚点转换为 Region 相对骨骼中心的偏移;
- 转换时必须处理 Spine 数学坐标 Y 向上与 Pixi 屏幕坐标 Y 向下的差异;
- 实现后必须使用非中心锚点和旋转状态进行视觉对照。
8.5 序列帧
一组序列帧始终只使用一根粒子骨骼,不因图片数量增加骨骼。
第一版不依赖 Spine 原生 Sequence 命名约束,而采用:
- 每张序列图片建立独立 Region 附件;
- 使用 Attachment Timeline 切换当前 Region;
- 按烘焙后的最终图片索引输出,不在导出端重新推演播放模式。
需要完整支持:
- 单次-尾帧消失;
- 单次-尾帧固定;
- 正向循环;
- 反向循环。
九、拖尾加权 Mesh 标准
9.1 禁止项
拖尾不得使用逐帧 attachments → deform 时间轴作为正式导出方案。
9.2 正式结构
拖尾直接转换为:
拖尾骨骼链 + 加权 Mesh + 骨骼动画
复用项目现有拖尾数据:
trailGridRows / trailGridCols生成网格拓扑;- 当前三角形索引写入
triangles; - 当前 UV 与图片旋转写入
uvs; trailSkinWeights中的boneA / boneB / weight转换为 Spine 加权 Mesh 顶点编码;trailState.bones转换为拖尾骨骼链动画;- 拖尾资源切换使用同一拖尾 Slot 下的多个 Mesh 附件和 Attachment Timeline;
- 拖尾颜色和透明度使用拖尾 Slot 的 RGBA Timeline。
9.3 拖尾动画映射
- 拖尾长度由骨骼链各节点位置体现;
- 拖尾方向由骨骼旋转体现;
- 拖尾宽度由骨骼垂直缩放体现;
- 拖尾形状曲线进入 Mesh 的绑定顶点分布;
- 拖尾图片旋转进入 UV;
- 拖尾头部必须与粒子最终渲染位置一致;
- 每帧世界状态转换为父子骨骼局部状态后再写入时间轴。
9.4 权重标准
- 每个顶点使用项目已有的相邻骨骼影响关系;
- 每个顶点权重和必须在允许误差内等于 1;
- 骨骼索引必须对应最终
bones数组顺序; - 不允许引用不存在或被排除的骨骼;
- 导出后需要检查弯曲、宽度变化、资源旋转和粒子旋转情况下的拖尾形态。
十、外部关联烘焙
10.1 通用规则
所有导出动画先执行一次独立、确定性的离线烘焙:
- 使用当前粒子系统随机种子重置模拟;
- 按导出 FPS 逐帧推进;
- 计算路径跟随、Spine 骨骼跟随、碰撞和全部修改器;
- 记录粒子和拖尾最终渲染状态;
- 将外部对象影响转换为系统根或粒子骨骼动画;
- JSON 中不保留任何外部对象引用。
10.2 碰撞
- 不导出碰撞体;
- 碰撞造成的位置、速度方向、暂停、销毁和反弹结果进入最终粒子动画;
- 碰撞突变前后必须保留关键帧,不能跨越突变进行平滑压缩。
10.3 路径跟随
- 不导出路径对象或 Path Constraint;
- 本地空间跟随烘焙为系统根运动与粒子局部运动;
- 世界空间跟随烘焙为粒子最终世界运动,已出生粒子不能错误继承后续路径移动;
- 路径方向和旋转表现按画布最终结果写入。
10.4 Spine 骨骼跟随
- 不导出原 Spine 对象或原目标骨骼;
- 跟随位置和用户设置的偏移进入最终动画;
- 不额外继承原 Spine 骨骼的缩放和旋转,保持编辑器现有语义;
- 目标失效时按编辑器当前默认回退逻辑处理。
10.5 坐标空间
不能只读取粒子局部快照直接输出。每帧必须组合:
粒子局部状态
+ 系统根变换
+ 当前帧跟随目标产生的有效变换
= 最终可导出状态
同时统一处理 Pixi Y 向下与 Spine Y 向上的坐标转换、旋转方向和父子局部变换。
十一、动画归属与时长
11.1 多动画
一个 JSON 包含项目中的多个“所属动画”:
"animations": {
"animation": {},
"animation2": {},
"start": {},
"loop": {},
"end": {}
}
- 每个粒子系统只写入它所属的动画;
- 多个粒子系统可以属于同一动画;
- 同一动画时长取参与导出的粒子系统中最长者;
- 较短系统到达末帧后保持符合自身模式的末帧状态;
- Spine、碰撞体和路径自身时长不参与导出动画时长计算。
11.2 空动画
空动画是否保留遵循“排除无内容动画”设置:
- 设置关闭:所属动画列表中的空动画仍输出为
{}; - 设置开启:没有任何可见粒子动画内容的动画不写入 JSON。
11.3 循环持续三段动画
- 启动段、纯循环段和结束段按用户当前保存的状态导出;
- 循环衔接帧的粒子身份和视觉状态必须稳定;
- 纯循环段保留假死粒子的骨骼身份,并通过附件隐藏或透明度 0 表现死亡;
- 循环首尾接缝不得因关键帧精简产生卡顿或突变;
- 延迟时间保持现有循环持续语义;
- 所属动画命名继续沿用编辑器已有逻辑,不由导出器自动改名。
11.4 时间端点
- 时间为
frameIndex / exportFps; - 时间轴包含可选择的最后端点帧;
- 循环动画允许保留首尾相同的末端点;
- 时长不足完整导出帧时按规则向上取整,不能截断最长寿命粒子或拖尾。
十二、关键帧烘焙与压缩
12.1 总体策略
采用:
完整逐帧烘焙 → 分类 → 安全精简 → 误差验证
不能先减少采样再模拟,也不能简单每隔固定帧保留一帧。
12.2 离散数据
以下数据不能进行数值插值,只保留变化点并使用阶跃语义:
- 粒子出生和死亡;
- 图片显示和隐藏;
- 粒子图片资源切换;
- 序列帧附件切换;
- 拖尾资源切换;
- 混合模式变化;
- 假死状态切换。
连续多帧相同附件或相同状态只输出第一次变化关键帧。
12.3 连续数据
以下数据先逐帧烘焙,再进行误差受控精简:
- 粒子位置;
- 粒子旋转;
- 粒子缩放;
- 粒子颜色和透明度;
- 拖尾骨骼位置;
- 拖尾骨骼旋转;
- 拖尾宽度缩放。
精简器检查删除中间关键帧后,Spine 插值结果是否仍在误差范围内。采用以下视觉容差:
| 数据 | 建议容差 |
|---|---|
| 粒子位置 | 0.05–0.1 像素(当前实现取 0.1) |
| 拖尾骨骼位置 | 0.05–0.1 像素(当前实现取 0.1) |
| 旋转 | 0.01° |
| 缩放 | 0.01 |
| 透明度 | 0.01 |
| RGB | 单通道 1/255 |
出生、死亡、附件切换、碰撞突变和循环接缝仍强制保留,不允许跨边界压缩。
12.4 强制保留点
以下位置不得跨越压缩:
- 粒子出生帧;
- 粒子死亡帧;
- 附件显示、隐藏和切换帧;
- 碰撞、反弹、暂停和销毁前后;
- 运动方向突然变化处;
- 拖尾出现和消失处;
- 循环首尾衔接区域;
- 延迟段和正式运动段边界;
- 旋转角度展开产生的边界。
12.5 旋转处理
压缩前先进行角度展开。例如:
358° → 1° → 4°
应转换为:
358° → 361° → 364°
避免 Spine 插值时反向旋转一整圈。
12.6 插值曲线设置
线性 (Linear):连续数据使用线性插值和线性误差精简;平滑贝塞尔 (Smooth Bézier):对连续段拟合贝塞尔,并逐帧检查误差;- 贝塞尔拟合不满足容差时必须增加关键帧,不能牺牲精度;
- 离散数据、突变点、碰撞边界和循环接缝不受平滑贝塞尔设置影响。
十三、导出设置标准
导出设置是全局编辑器设置,不属于单个粒子系统。必须参与:
- 保存配置;
- 加载配置;
- 预设加载;
- 撤回;
- 旧配置默认值补齐。
13.1 设置项与默认值
| 设置 | 默认值 | 规则 |
|---|---|---|
| 图片路径 | ./images/ |
写入 skeleton.images |
| Spine 版本 | Spine 4.2 |
第一版唯一选项 |
| 关键帧插值曲线 | 线性 (Linear) |
可切换平滑贝塞尔 |
| 导出 FPS | 30 |
支持 1~240 的正整数 |
| 不写 fps | 关闭 | 只省略 skeleton.fps 元数据 |
| 整数帧对齐 | 开启 | 关键帧位于导出 FPS 的整数帧网格 |
| 骨骼对象池 | 开启 | 复用粒子骨骼和拖尾链 |
| 排除无内容动画 | 关闭 | 关闭时保留空动画 {} |
| 默认文件名 | SpineParticle.json |
浏览器处理重复下载名称 |
13.2 导出 FPS 语义
修改导出 FPS 时保持动画实际秒数不变。
例如:
30f / 30 FPS = 1 秒
60f / 60 FPS = 1 秒
不能在导出 60 FPS 时仍只输出 30 帧并把动画缩短为 0.5 秒。
“不写 fps”仅省略 Spine JSON 中的 FPS 元数据,内部烘焙、采样和时间换算仍使用导出 FPS。
13.3 整数帧对齐
开启时:
time = integerFrame / exportFps
不能产生小数帧位置。无法整除的尾端时长向上取整,同时保持需要完成的粒子生命周期和拖尾状态。
十四、命名与文件规则
14.1 默认文件名
SpineParticle.json
14.2 名称安全
导出器必须:
- 为系统、粒子、拖尾、Slot 和 Attachment 生成稳定名称;
- 处理空名称、重复名称和非法路径分隔符;
- 保留用户所属动画名称;
- 不在没有必要时修改用户可见的图片文件名;
- 保证同一配置、同一种子和同一导出设置产生稳定命名。
十五、代码结构标准
导出功能必须使用独立文件,不能把大量逻辑继续堆入 ParticlePanel.vue、Stage.vue 或 Store。
推荐结构:
src/export/
├─ spineExportSettings.ts
├─ spineJsonTypes.ts
├─ particleExportBaker.ts
├─ spineMeshBuilder.ts
├─ spineKeyframeReducer.ts
├─ spineJsonExporter.ts
└─ spineJsonValidator.ts
职责:
spineExportSettings.ts:导出设置类型、默认值和旧配置补齐;spineJsonTypes.ts:Spine 4.2 JSON 类型;particleExportBaker.ts:确定性逐帧模拟和外部关联解除;spineMeshBuilder.ts:拖尾骨骼链、权重、UV 和三角形生成;spineKeyframeReducer.ts:离散合并和连续时间轴误差精简;spineJsonExporter.ts:组装 Skeleton、Bones、Slots、Skins 和 Animations;spineJsonValidator.ts:导出前后结构验证和警告。
界面中的“导出Spine Json”按钮只负责调用导出入口、显示结果和下载文件。
十六、验证与验收标准
16.1 结构验证
导出前检查:
- 骨骼名称唯一;
- 父骨骼先于子骨骼;
- Slot 引用的骨骼存在;
- Skin 引用的 Slot 存在;
- Attachment Timeline 引用的附件存在;
- Mesh 骨骼索引有效;
- Mesh 权重和正确;
- UV、顶点和三角形索引数量匹配;
- 动画时间递增;
- 颜色为有效 RGBA;
- 所有数字有限,不出现
NaN或Infinity。
16.2 Runtime 验证
生成 JSON 后,使用项目内 Spine 4.2 Runtime 进行一次解析验证。解析失败时不应下载伪成功文件,应显示明确错误位置。
图片缺失不属于 JSON 结构失败,只显示警告。
16.3 视觉验证
至少对以下帧进行编辑器画布与导出结果对照:
- 第一帧;
- 粒子第一次出生帧;
- 最大粒子数量附近;
- 图片或序列帧切换帧;
- 碰撞发生前后;
- 路径或 Spine 跟随运动中间帧;
- 拖尾明显弯曲帧;
- 最后一帧;
- 纯循环首帧和末帧。
对照内容包括:
- 粒子数量;
- 粒子位置;
- 旋转与缩放;
- 图片资源;
- 颜色与透明度;
- 绘制顺序;
- 拖尾位置、方向、宽度和弯曲;
- 循环接缝。
16.4 文件体积验收
- 优先通过对象池、重复状态合并和误差受控关键帧精简减小文件;
- 拖尾必须使用加权 Mesh,不能用逐帧 Deform 换取实现简单;
- 不能为了缩小文件破坏碰撞、噪声、序列帧或循环精度;
- 对象池关闭时允许文件显著增大,但应给出预计规模提示。
十七、当前实施状态
截至本文落盘:
- 导出范围、格式目标和关键规则已对齐;
- 导出设置面板已实现;
- 导出设置已接入保存、加载、预设、撤回和旧配置补齐;
- 默认文件名已定义为
SpineParticle.json; - “导出Spine Json”按钮尚未接入 JSON 生成;
- 正式导出代码必须等待用户明确的“开始”指令后实施;
- 开始实现前应下载并核对 Spine 官方 GitHub 仓库中的 Spine 4.2 加权 Mesh 和多动画 JSON 示例。
十八、禁止偏离项摘要
以下规则未经重新确认不得改变:
- 只导出可见粒子系统;
- 不导出碰撞体、路径和原 Spine 对象;
- 外部关联必须烘焙为独立动画;
- 第一版只支持 Spine 4.2;
- 图片文件不导出,只写正确路径;
- 缺图不阻止导出;
- 序列帧只使用一根粒子骨骼;
- 拖尾必须使用加权 Mesh 和拖尾骨骼链;
- 拖尾不得正式导出为逐帧 Deform;
- 先逐帧烘焙,再安全精简关键帧;
- Setup Pose 普通骨骼位移和旋转为 0、缩放为 1;
- 拖尾子骨骼保留正确绑定链位置;
- Setup Pose 图片和 Mesh 默认透明度为 0;
- 修改 FPS 时保持实际秒数不变;
- 空动画是否保留遵循“排除无内容动画”;
- 默认文件名为
SpineParticle.json; - 导出功能必须拆分为独立代码模块;
- 导出主要用途是重新导入 Spine 编辑器继续编辑。