Files
SpineParticlesWeb/Document/网页粒子系统阶段十.md
2026-09-02 10:45:10 +08:00

15 KiB
Raw Permalink Blame History

网页粒子系统 · 阶段十

阶段定位:粒子图片序列帧与循环持续三段动画体系定版
完成日期:2026-08-31
工程目录:/Users/tianmokeji/Desktop/SpineParticle
技术栈:Vue 3 + TypeScript + Pinia + PixiJS 7 + Spine Runtime 4.2 + Vite


一、阶段结论

阶段十在阶段九配置持久化、撤回和预设体系的基础上,扩展了粒子图片资源的序列帧能力,并完成了持续发射模式下“启动—循环—结束”三段动画的编辑和预览模型。

图片资源现在可以在固定图片和序列帧之间切换。每个序列帧资源仍属于同一个粒子和同一根粒子骨骼,只在播放过程中替换纹理,不会因为一组序列图而生成多根粒子骨骼。

持续发射模式新增“常规持续”和“循环持续”。循环持续通过稳定周期预演、确定性随机序列、完整帧缓存和假死粒子状态解决首尾衔接问题,并支持分别生成启动段、纯循环段和结束段。

本阶段主要完成:

  1. 图片资源增加固定图片与序列帧两种模式;
  2. 支持多选图片并按自然文件名顺序组成序列;
  3. 支持单次尾帧消失、单次尾帧固定、正向循环和反向循环;
  4. 支持独立序列帧播放帧率;
  5. 序列帧状态纳入粒子录制、回放、保存、加载和撤回;
  6. 持续发射增加常规持续与循环持续两种表现;
  7. 循环时长使用独立整数帧参数,不覆盖常规持续秒数;
  8. 实现启动段、纯循环段、结束段三种互斥表现;
  9. 建立统一的循环衔接帧;
  10. 使用周期预演避免末帧硬复制造成的运动突变;
  11. 使用透明度为 0 的假死粒子保持纯循环段骨骼集合稳定;
  12. 支持循环模式下的延迟时间与首帧保持;
  13. 循环模式自动禁用并重置 Spine 骨骼跟随和路径跟随;
  14. 修复循环重新计算期间缓存帧与实时状态交替造成的闪烁;
  15. 时间轴支持选择包含结束端点的最后一帧;
  16. 多粒子系统独立计算,整体时间轴继续取粒子和 Spine 中最长者;
  17. 完成 TypeScript 与 Vite 生产构建验证。

二、图片序列帧资源

2.1 图片模式

每张粒子图片资源卡片增加“图片模式”:

模式 说明
固定 粒子生命周期内始终使用同一张图片
序列帧 按粒子出生后的时间依次切换多张图片

模式属于单个图片资源卡片。一个粒子系统可以同时存在多个图片资源,每个资源可以分别选择固定图片或序列帧,并继续使用原有权重随机选择逻辑。

资源卡片原有参数保持不变,包括:

  • 权重与权重锁定;
  • 缩放;
  • 锚点;
  • 颜色模式与颜色渐变;
  • 混合模式;
  • 独立透明度与透明度曲线。

2.2 序列图片选择

选择序列帧时允许一次多选图片。编辑器会按文件名进行自然排序,而不是简单字符串排序。

例如:

diwen_1.png
diwen_2.png
diwen_10.png

会按照 1 → 2 → 10 排列。

界面明确显示实际播放顺序:

已选择 13 帧,按 diwen_000.png-diwen_012.png 顺序播放

阶段测试资源位于:

public/序列帧测试/sg/

2.3 播放模式

序列帧支持四种播放模式:

模式 行为
单次-尾帧消失 正向播放一次,超过最后一张后隐藏粒子图片
单次-尾帧固定 正向播放一次,之后保持最后一张图片
正向循环 第一张播放到最后一张,再回到第一张
反向循环 最后一张播放到第一张,再回到最后一张

“尾帧消失”只隐藏粒子图片。粒子逻辑、粒子骨骼和拖尾仍可继续存在,直到粒子生命周期结束。

2.4 播放帧率

每个序列帧资源拥有独立播放帧率:

sequenceFps

有效范围为 1120 FPS,默认 30 FPS。序列帧索引根据粒子实际出生时间计算,不依赖浏览器刷新次数。

2.5 单粒子单骨骼原则

序列帧不会为每张图片创建独立骨骼。

运行规则为:

一个粒子实例 = 一个粒子骨骼 = 一个 Sprite
多张序列图片 = 同一个 Sprite 在不同时间替换 Texture

因此 13 张序列图片仍只使用一根粒子骨骼,避免序列帧数量直接放大骨骼数量。

2.6 录制和持久化

粒子逐帧状态增加:

imageFrameIndex
imageVisible

录制和回放会恢复:

  • 当前序列帧索引;
  • 当前纹理;
  • 当前图片显隐;
  • 资源锚点;
  • 资源混合模式。

配置保存会保存序列帧文件名、预览数据和播放参数;加载时重新创建纹理。撤回快照也包含序列帧资源配置,因此选择图片、切换模式和调整播放方式均可撤回。


三、持续发射表现模式

3.1 两种表现

持续发射模式下增加:

表现 说明
常规持续 保持原持续发射逻辑,结束发射后等待存活粒子死亡
循环持续 生成可以拆分为启动、循环和结束的稳定周期动画

发射速率等已有参数继续共用。常规持续时长和循环持续时长分别保存,不会互相覆盖。

3.2 独立时长数据

常规持续继续使用:

duration: number // 秒

循环持续新增:

loopDurationFrames: number // 整数帧

默认循环时长为 30f,可编辑范围为 1~1800f。播放仍固定按照:

30f/s

旧配置没有 loopDurationFrames 时,会把原持续秒数乘以 30 并向上取整作为迁移初值。此后两种时长完全独立。

例如:

常规持续 = 1.00s
循环持续 = 54f

在两种表现之间切换不会改变对方的数值。


四、循环持续三段动画

4.1 三种状态

循环持续面板包含两个附加开关:

  • 生成开始循环动画;
  • 生成结束循环动画。

两个开关互斥,不能同时开启。

开始开关 结束开关 当前生成内容
纯循环段
启动—循环段
循环—结束段

4.2 循环衔接帧

稳定循环状态的周期边界称为“循环衔接帧”。它包含:

  • 粒子骨骼集合;
  • 粒子位置、旋转和缩放;
  • 颜色与透明度;
  • 图片资源与序列帧索引;
  • 图片显隐;
  • 拖尾骨骼、宽度、颜色和透明度;
  • 修改器计算后的最终结果。

启动段末端、纯循环段周期边界和结束段起点使用同一套确定性计算规则。

4.3 启动段

启动段规则:

  1. 第一帧完全为空;
  2. 粒子骨骼数量为 0
  3. 延迟期间保持空帧;
  4. 延迟结束后开始正常生成粒子;
  5. 粒子使用正常生命周期,可以在启动过程中死亡;
  6. 系统自然预热到稳定循环状态;
  7. 最后一帧到达循环衔接状态。

当最大粒子寿命跨越多个循环周期时,启动段会自动使用足够的预热周期,保证末端确实进入稳定循环分布。

4.4 纯循环段

纯循环段规则:

  1. 延迟期间保持循环衔接帧;
  2. 延迟结束后播放一个完整循环周期;
  3. 周期长度由 loopDurationFrames 决定;
  4. 发射事件、随机参数和资源选择在每个周期使用相同确定性序列;
  5. 周期末端由真实模拟自然到达下一周期起点;
  6. 不再把末帧强制替换为首帧。

这一实现保证的不只是边界两个快照一致,还保证倒数帧到结束端点、结束端点到下一周期的运动连续,不会在最后两帧突然跳变或卡顿。

4.5 结束段

结束段规则:

  1. 第一帧为循环衔接状态;
  2. 延迟期间保持该衔接状态;
  3. 延迟结束后立即停止生成新粒子;
  4. 已存在粒子继续按正常生命周期运行;
  5. 拖尾随粒子继续更新;
  6. 最后一帧所有粒子和拖尾消失。

结束段不使用发射时长作为消亡长度。长度根据衔接帧中粒子的最大剩余生命和拖尾状态自动计算。


五、稳定循环计算

5.1 完整周期预演

早期实现只把纯循环末帧复制为首帧。该方式虽然能让两个快照数值相同,却会使倒数帧直接跳到衔接状态,造成明显卡顿。

当前流程改为:

  1. 根据循环时长计算每周期帧数;
  2. 根据最大粒子寿命计算需要预演的周期数;
  3. 从确定性随机种子开始模拟;
  4. 每个新周期重置发射计时和随机序列;
  5. 保留跨周期仍存活粒子的物理状态;
  6. 预演到粒子分布稳定;
  7. 记录下一完整周期及结束端点;
  8. 时间轴循环时直接回放缓存结果。

5.2 周期随机序列

每个周期重新开始:

  • 发射累计器;
  • 发射计时;
  • 粒子生成序号;
  • 全局随机源;
  • 与发射周期相关的吸附计时。

仍存活粒子不会在周期边界被重置,其运动会继续自然推进。

噪声相位、拖尾资源采样和吸附曲线方向改为使用周期内粒子生成序号,不再依赖粒子池槽位。即使粒子池复用了不同编号,也不会改变下一周期相同发射事件的视觉属性。

5.3 假死粒子

纯循环段需要保持粒子骨骼集合稳定。某粒子在某些帧已按正常生命周期死亡时,录制缓存不会直接删除对应骨骼,而是写入假死状态:

active = true
alpha = 0
imageVisible = false
trailState = undefined

因此:

  • 视觉上粒子已经死亡;
  • 图片和拖尾均不可见;
  • 逻辑上粒子骨骼仍存在;
  • 周期内不会因为骨骼突然增删破坏衔接;
  • 后续正常出现时仍可继续使用同一骨骼轨道。

假死只用于纯循环段。启动段和结束段仍使用正常粒子死亡逻辑。

5.4 缓存帧闪烁修复

循环段会在录制首帧一次性生成完整缓存。此前在全局时间轴第一次录制结束前,固定帧之间仍会调用 update(0) 显示粒子内部实时状态,导致画面在以下两套状态之间交替:

  • 已计算好的循环缓存帧;
  • 周期预演结束后的内部状态。

表现为重新计算后粒子高频闪烁,直到时间轴完整运行一遍才恢复。

当前逻辑在循环缓存存在后立即全程读取缓存,不再夹杂实时状态。


六、延迟时间

循环持续继续使用原“延迟时间”参数,三种状态均支持。

状态 延迟期间保持内容
启动段 空的第一帧
纯循环段 循环衔接帧
结束段 循环衔接帧

延迟结束后才开始推进对应动画。

时间轴中:

  • 粒子条左侧位置继续表示延迟;
  • 可以拖动粒子条调整延迟;
  • 整体播放长度包含延迟帧;
  • 延迟期间画布不是重复重新计算,而是保持第一帧缓存。

七、跟随功能限制

循环持续不与 Spine 骨骼跟随或路径跟随联动。原因是外部目标动画或路径进度可能不具备相同周期,无法保证粒子周期边界稳定。

进入或退出循环持续时均弹出提示:

粒子跟随设置会失效并恢复默认值

只有用户确认后才切换。

确认后重置:

  • 发射器跟随总开关;
  • 跟随模式;
  • 路径 ID
  • Spine ID 与骨骼名;
  • 跟随空间和方向;
  • 路径进度曲线;
  • 位移、旋转和缩放偏移。

循环持续期间跟随控件不可重新开启。切回常规持续后控件恢复可用,但不会自动恢复进入循环前的旧跟随设置。


八、时间轴规则

8.1 结束端点

时间轴内部保存的是快照数量,界面显示的是最后一个可选帧编号。

例如动画长度为 54f

可选帧:0f54f
快照数量:55

因此:

  • 可以拖动到第 54 帧;
  • “移动到最后一帧”会到达第 54 帧;
  • 后一帧按钮会正确限制在第 54 帧;
  • 非循环播放会停在第 54 帧。

8.2 轨道显示

状态 时间轴表现
常规持续 绿色发射段 + 红色粒子存活尾段
启动段 延迟偏移 + 启动预热发射段
纯循环段 延迟偏移 + 一个完整循环周期
结束段 延迟偏移 + 只有粒子存在/消亡段

结束段不显示可调整的绿色发射时长,因为该段不会产生新粒子。

8.3 多系统与 Spine

每个粒子系统独立计算自己的:

  • 循环时长;
  • 预热周期;
  • 循环衔接状态;
  • 启动或结束长度;
  • 延迟帧。

整体时间轴仍取以下对象的最长结束时间:

  • 全部粒子系统;
  • 当前加载并选择动画的 Spine 对象;
  • 已存在的其他时间轴场景动画数据。

较短粒子系统到达末端后保持末帧,直到整体时间轴结束。


九、配置、预设与撤回联动

阶段十新增字段均属于粒子系统配置:

streamBehavior
loopDurationFrames
generateLoopStartAnimation
generateLoopEndAnimation
imageMode
sequencePlayback
sequenceFps
sequenceFrames

因此它们自动纳入:

  • JSON 配置保存;
  • JSON 配置加载;
  • public/Preset/ 预设加载;
  • 对象复制;
  • 编辑器撤回快照;
  • 模块重置。

加载旧配置时会补齐默认值,并处理:

  • once 序列模式迁移为 once-hold
  • loop 序列模式迁移为 loop-forward
  • 缺少循环时长时从旧持续秒数换算初值;
  • 启动和结束开关同时为真时自动保留启动段、关闭结束段;
  • 缺少序列帧字段时恢复固定图片模式。

粒子逐帧缓存不写入配置。配置加载、撤回或参数修改后会根据当前确定性配置重新计算。


十、主要代码落点

文件 阶段十职责
src/core/particleEmitter.ts 序列帧纹理切换、循环配置字段、强制/停止发射控制、周期随机源重启
src/views/ImageResourceCard.vue 图片模式、播放模式、播放帧率、序列文件和顺序提示
src/views/ParticlePanel.vue 序列帧选择、循环持续面板、独立帧时长、互斥开关、跟随重置确认
src/views/Stage.vue 三段动画烘焙、周期预演、衔接状态、假死粒子、缓存回放与闪烁修复
src/views/Timeline.vue 循环轨道宽度、延迟偏移、结束段显示和末端帧选择
src/store/particleStore.ts 三种循环状态总帧数、多系统和 Spine 最长时间计算
src/editor/editorConfig.ts 序列图片数据保存、纹理重建和旧配置恢复

十一、验证结果

本阶段完成以下静态与构建验证:

npm run build

结果:

  • vue-tsc -b 通过;
  • Vite 生产构建通过;
  • 548 个模块完成转换;
  • 无 TypeScript 错误;
  • 无构建错误;
  • 仅保留既有的大包体积提示。

交互修复过程中已覆盖:

  • 循环时长与常规持续时长独立;
  • 纯循环末端不再硬复制首帧;
  • 延迟期间保持第一帧;
  • 时间轴可以到达结束端点;
  • 重新计算期间不再交替显示内部实时状态;
  • 配置字段具备旧数据迁移默认值。

十二、阶段十最终状态

阶段十完成后,编辑器已经具备:

  • 单图和序列帧混合资源;
  • 多种序列播放方式;
  • 确定性粒子序列帧录制;
  • 常规持续与独立循环持续;
  • 启动、循环、结束三段动画生成;
  • 稳定周期预演;
  • 假死粒子骨骼保持;
  • 延迟首帧保持;
  • 多系统时间轴对齐;
  • 配置、预设、复制和撤回联动。

至此,阶段十“序列帧资源与循环持续动画体系”完成落盘。