# 网页粒子系统 · 阶段七 > 阶段定位:**Spine 4.2 骨架资源接入、统一场景变换与碰撞体路径跟随定版** > 完成日期:2026-08-29 > 工程目录:`/Users/tianmokeji/Desktop/SpineParticle` > 技术栈:Vue 3 + TypeScript + Pinia + PixiJS 7 + Spine Runtime 4.2 + Vite --- ## 一、阶段结论 阶段七完成了 Spine 骨架场景对象的第一版完整接入,并补齐了时间轴、场景变换和碰撞体路径跟随能力。Spine 资源现在可以离线加载、显示、选择动画、查看骨骼层级,并与粒子系统共同受统一的 30 FPS 时间轴控制。 本阶段主要完成: 1. 接入 Spine 官方 4.2 PixiJS 7 运行时并离线落盘; 2. 实现 Spine 骨架场景对象及独立属性面板; 3. 支持 JSON、SKEL、Atlas 和多张纹理资源加载; 4. 自动读取动画列表、动画时长和骨骼层级; 5. Spine 动画关闭自身循环,改由编辑器时间轴统一驱动; 6. 时间轴增加紫色 Spine 动画条和逐帧控制按钮; 7. 修复动画按浏览器刷新次数推进导致的播放过快问题; 8. 统一画布变换工具,使其作用于场景树当前选中的对象; 9. 为碰撞体和路径补充缩放变换; 10. 实现碰撞体沿路径移动、速度曲线和方向跟随; 11. 统一“路径”术语,移除重复的移动轨迹显示开关; 12. 完成旧场景字段补齐和热更新兼容处理。 --- ## 二、Spine 官方运行时接入 ### 2.1 运行时来源 项目使用 Spine 官方仓库中的 4.2 兼容版本: | 项目 | 内容 | |---|---| | 官方仓库 | `https://github.com/EsotericSoftware/spine-runtimes` | | 兼容分支 | `4.2` | | 固定提交 | `b81e5a58ed38704aee4f866f0e0ac672623ce914` | | `spine-core` | `4.2.119` | | `spine-pixi-v7` | `4.2.119` | | 渲染目标 | PixiJS 7 | 运行时代码放置在 `vendor/spine/`,通过 `file:` 依赖接入: ```text @esotericsoftware/spine-core -> vendor/spine/spine-core @esotericsoftware/spine-pixi-v7 -> vendor/spine/spine-pixi-v7 ``` 因此项目构建时不需要从 npm 在线下载 Spine 运行时代码。版本来源、提交号和许可提示记录在 `vendor/spine/SOURCE.md`,官方许可证保存在同目录中。 ### 2.2 代码拆分 Spine 功能没有继续堆叠到主面板和主画布文件中,而是拆分为: | 文件 | 职责 | |---|---| | `spineTypes.ts` | Spine 场景对象、动画和骨骼元数据类型 | | `spineAssetLoader.ts` | 读取骨架、Atlas 和纹理并生成 SkeletonData | | `spineAssetRegistry.ts` | 管理运行时资源和纹理释放 | | `SpineRuntimeLayer.ts` | 创建 Spine 显示对象并按编辑器帧同步动画 | | `SpineObjectPanel.vue` | 资源选择、属性、动画列表和层级树界面 | 这种拆分让主粒子系统逻辑与第三方骨架运行时保持边界,便于后续增加插槽、皮肤、混合和导出功能。 --- ## 三、Spine 场景对象 ### 3.1 创建与默认状态 点击场景对象模块中的 `+骨架` 会创建一个 Spine 对象,并自动成为当前选中对象。 | 参数 | 默认值 | |---|---:| | 名称 | `SpineSkeleton1` | | 启用 | 开启 | | X / Y | 0 / 0 | | 旋转 | 0° | | Scale X / Y | 1 / 1 | | 开始时间 | 0 秒 | | 资源状态 | 未加载 | | 当前动画 | 无 | Spine 对象与粒子系统、碰撞体和路径统一显示在场景对象树中,支持选择和删除。删除对象时会同步释放已注册的 Spine 资源和纹理引用。 ### 3.2 支持的资源 加载一套 Spine 资源时需要选择: - 骨架数据:`.json` 或 `.skel`; - 图集描述:`.atlas`; - 纹理图片:`.png`、`.jpg`、`.jpeg`、`.webp`,允许多选; - 兼容文件选择器中的 `.wepb` 拼写。 加载器按 Atlas 页面的文件名匹配所选纹理。如果 Atlas 引用了未选择的纹理,会给出明确错误,不会创建不完整的骨架对象。 ### 3.3 测试资源 项目 `public/spine/` 中的 Spine 4.2 测试资源用于本阶段验证: - `bingo.json`; - `bingo.atlas`; - `bingo.png`; - `bingo_2.png`。 测试覆盖了 JSON 骨架、多纹理 Atlas、动画列表读取、画布渲染和骨骼层级展示。 --- ## 四、动画与骨骼层级 ### 4.1 动画列表 资源加载成功后,面板会从 SkeletonData 中读取全部动画: - 显示动画名称; - 显示真实动画时长,单位为秒; - 支持选择“无”或任意动画; - 默认选择资源中的第一个动画; - 切换动画后重新计算时间轴总长度并回到第 0 帧。 Spine 动画自身不循环播放。动画到达末尾后停留在末帧,是否重新从头播放由编辑器总时间轴的循环按钮决定。 ### 4.2 骨骼层级树 加载成功后同时读取骨骼名称、父级关系和深度,按层级显示为树结构。 层级树支持: - 点击父骨骼前的箭头折叠或展开子级; - “全部折叠”和“全部展开”; - 折叠父级后隐藏其全部后代; - 长层级树在固定高度区域内滚动。 该树当前用于查看资源结构,尚未提供骨骼选择、单骨骼变换或插槽编辑。 ### 4.3 Spine 资源显示设置 原属性面板中容易误解的“启用骨架显示”已改为系统设置中的“启用 Spine 资源显示”。 - 已加载包含动画的 Spine 资源时,可以全局显示或隐藏 Spine 资源; - 没有可用 Spine 动画时,该设置置灰; - 该开关只控制画布中的 Spine 资源,不影响编辑器自身的粒子拖尾骨骼、骨骼连线或蒙皮网格调试显示; - 对象自身的 `enabled` 状态仍会独立参与最终可见性判断。 --- ## 五、统一时间轴 ### 5.1 真实时间驱动 时间轴继续使用统一的 **30 FPS** 基准: ```text 1 秒 = 30 帧 当前动画时间 = 当前帧 / 30 - Spine 开始时间 ``` 修复前,Spine 动画会在浏览器每次刷新画面时前进一帧。高刷新率屏幕上动画会明显快于 Spine 编辑器中的同一动画。 现在使用实际经过时间累积,并按 `1/30` 秒的固定步长推进显示帧。浏览器刷新率只影响画面刷新平滑度,不再改变动画播放速度。 ### 5.2 Spine 紫色动画条 选择有效 Spine 动画后,时间轴新增紫色动画条: - 条带长度来自 Spine 动画的真实时长; - 长度不可拖动修改; - 整条可以左右拖动; - 左侧空白表示延迟播放时间; - 拖动以 1 帧为单位吸附; - 没有动画数据或当前动画为“无”时不显示。 Spine 动画、粒子系统和碰撞体路径移动共同参与总时间轴长度计算: ```text 总时长 = max( 粒子系统最晚消失时间, Spine 开始时间 + Spine 动画时长, 碰撞体路径移动时长 ) ``` ### 5.3 播放控制 时间轴控制区现在包括: | 控制 | 行为 | |---|---| | 播放 / 暂停 | 切换整体时间轴播放状态 | | 回到第一帧 | 跳转到第 0 帧 | | 前一帧 | 自动暂停并后退 1 帧 | | 后一帧 | 自动暂停并前进 1 帧 | | 移动到最后一帧 | 自动暂停并跳转到最后帧 | | 循环 | 控制整体时间轴到达末尾后的行为 | 这些操作统一影响粒子模拟、Spine 动画和碰撞体路径移动。 --- ## 六、场景对象变换统一 ### 6.1 当前选中对象 画布左上角的位移、旋转和缩放工具不再固定操作粒子系统,而是读取场景树中的当前选中对象。 支持的对象包括: - 粒子系统; - 碰撞体; - 路径; - Spine 骨架。 选择 Spine 对象后,变换工具只修改该 Spine 对象;选择碰撞体或路径后,同样只影响选中对象。 ### 6.2 缩放补齐 碰撞体新增 `scaleX`、`scaleY`,路径继续使用独立的 `scaleX`、`scaleY`。两类对象均可通过属性面板或画布缩放工具修改。 路径的位移、旋转和缩放会同时作用于: - 路径曲线显示; - 锚点和贝塞尔手柄; - 发射器路径采样; - 碰撞体路径跟随。 碰撞体缩放同时影响画布轮廓和实际粒子碰撞计算。 --- ## 七、碰撞体路径跟随 阶段六预留的“跟随路径移动”在本阶段完成运行时实现。 ### 7.1 默认参数 | 参数 | 默认值 | |---|---:| | 跟随路径移动 | 关闭 | | 目标路径 | 未选择 | | 移动时长 | 2 秒 | | 曲线模式 | 跟随导出 | | 移动进度曲线 | 0→1 线性 | | 方向沿路径 | 关闭 | 只有开启跟随并选择一条已启用且包含锚点的路径后,碰撞体才会开始移动。无效或已删除的目标路径不会改变碰撞体原始位置。 ### 7.2 移动计算 ```text 归一化时间 = clamp(当前时间 / 移动时长, 0, 1) 路径进度 = 移动进度曲线(归一化时间) 碰撞体位置 = 路径按长度采样(路径进度) ``` 路径采样会考虑路径对象自身的位移、旋转和缩放。每段三次贝塞尔曲线先离散采样并累计实际距离,再按总长度查找位置,减少不同曲线段参数长度不一致造成的明显速度变化。 面板提供三种曲线模式: - 跟随导出; - 线性; - 贝塞尔。 曲线编辑器横轴表示实时除以移动时长,纵轴表示路径进度。到达移动时长后,碰撞体停留在路径终点;编辑器时间轴循环时再从起点开始。 ### 7.3 方向沿路径 “方向沿路径”默认关闭: - 关闭时,碰撞体移动过程中保持自己的旋转值; - 开启时,根据路径当前位置前后采样点计算切线方向; - 碰撞体属性中的旋转值作为附加角度叠加,可继续微调朝向。 圆形碰撞体视觉上不容易观察旋转变化,矩形、椭圆和多边形更适合检查该功能。 ### 7.4 碰撞运行时 路径跟随不仅改变画布上的碰撞体预览位置,也会把同一份动态位置和旋转传给粒子碰撞检测。因此粒子会与移动中的碰撞体发生真实交互,物理、暂停和销毁三种响应保持有效。 运行时使用预览副本计算动态位置,不会持续覆盖碰撞体存储的基础 X、Y 和旋转值。关闭跟随后,碰撞体会恢复到属性面板中设置的基础变换。 路径对象本身始终在画布显示,因此移除了重复的“显示移动轨迹线”开关和额外轨迹覆盖层。 --- ## 八、术语与兼容性 ### 8.1 路径术语统一 用于贝塞尔对象和跟随功能的界面术语统一为“路径”: - 跟随路径移动; - 目标路径; - 路径进度; - 路径名称; - 闭合路径; - 路径颜色; - 发射器跟随路径。 发射器形状中的“轨道”仍表示粒子发射形状 `orbit`,不是场景路径对象,因此保留原名称。 ### 8.2 旧数据补齐 旧场景或热更新状态中的碰撞体可能缺少路径跟随字段。面板会即时补齐: - 目标路径; - 移动时长; - 曲线模式; - 移动进度曲线; - 方向沿路径。 曲线组件同时提供空值回退,避免旧数据加载或热更新瞬间因曲线为空导致界面渲染失败。 --- ## 九、验证结果 本阶段完成以下验证: - Spine 官方 4.2.119 本地运行时依赖和生产构建; - JSON、Atlas 和两张 PNG 测试资源加载; - 动画名称、真实时长和骨骼层级读取; - Spine 动画非循环播放及末帧保持; - 30 FPS 真实时间推进,不受浏览器刷新率影响; - 紫色 Spine 时间轴条长度和开始时间拖动; - 前一帧、后一帧和最后一帧自动暂停; - 骨骼层级单节点折叠和全部折叠; - Spine 资源全局显示开关和无动画时置灰; - 当前选中粒子、碰撞体、路径和 Spine 对象的画布变换; - 碰撞体和路径缩放与运行时表现同步; - 碰撞体目标路径、移动时长、进度曲线和方向开关; - 移动碰撞体参与实际粒子碰撞; - 路径术语统一及重复轨迹开关移除; - 旧碰撞体字段和曲线空值兼容; - 页面面板交互检查; - `npm run build` 生产构建通过; - `git diff --check` 通过。 构建仍有 Vite 对主产物体积超过 500 kB 的提示,不影响当前功能和构建结果,后续可通过按模块动态加载进一步优化。 --- ## 十、当前限制 1. Spine 资源通过本地文件选择器加载,刷新页面后需要重新选择,尚未纳入工程保存格式; 2. Spine 层级树当前只读,不能编辑骨骼、插槽、皮肤或约束; 3. Spine 动画尚未支持混合、播放速度、反向和多轨道叠加; 4. `.skel` 已接入官方二进制解析器,但本阶段主要使用 JSON 测试资源验证; 5. 碰撞体路径跟随当前为单次起点到终点,尚未提供往返或独立循环模式; 6. 自定义碰撞体仍使用规则多边形轮廓,尚未接入自由顶点编辑; 7. 场景对象和资源尚未形成完整的保存、导入和导出格式。 --- ## 十一、阶段八建议 1. 建立场景工程保存格式,持久化粒子、路径、碰撞体和 Spine 对象配置; 2. 将 Spine 资源复制到工程资源目录,支持刷新后自动恢复; 3. 增加 Spine 皮肤、插槽、混合时长和播放速度控制; 4. 为碰撞体路径跟随增加循环、往返、反向和结束行为; 5. 实现碰撞标签过滤和碰撞事件输出; 6. 实现自定义碰撞体自由顶点编辑; 7. 对 Spine 和曲线编辑器进行动态加载,降低主包体积; 8. 建立可复现的场景回归测试,覆盖统一时间轴和多对象组合。