15 KiB
网页粒子系统 · 阶段十
阶段定位:粒子图片序列帧与循环持续三段动画体系定版
完成日期:2026-08-31
工程目录:/Users/tianmokeji/Desktop/SpineParticle
技术栈:Vue 3 + TypeScript + Pinia + PixiJS 7 + Spine Runtime 4.2 + Vite
一、阶段结论
阶段十在阶段九配置持久化、撤回和预设体系的基础上,扩展了粒子图片资源的序列帧能力,并完成了持续发射模式下“启动—循环—结束”三段动画的编辑和预览模型。
图片资源现在可以在固定图片和序列帧之间切换。每个序列帧资源仍属于同一个粒子和同一根粒子骨骼,只在播放过程中替换纹理,不会因为一组序列图而生成多根粒子骨骼。
持续发射模式新增“常规持续”和“循环持续”。循环持续通过稳定周期预演、确定性随机序列、完整帧缓存和假死粒子状态解决首尾衔接问题,并支持分别生成启动段、纯循环段和结束段。
本阶段主要完成:
- 图片资源增加固定图片与序列帧两种模式;
- 支持多选图片并按自然文件名顺序组成序列;
- 支持单次尾帧消失、单次尾帧固定、正向循环和反向循环;
- 支持独立序列帧播放帧率;
- 序列帧状态纳入粒子录制、回放、保存、加载和撤回;
- 持续发射增加常规持续与循环持续两种表现;
- 循环时长使用独立整数帧参数,不覆盖常规持续秒数;
- 实现启动段、纯循环段、结束段三种互斥表现;
- 建立统一的循环衔接帧;
- 使用周期预演避免末帧硬复制造成的运动突变;
- 使用透明度为 0 的假死粒子保持纯循环段骨骼集合稳定;
- 支持循环模式下的延迟时间与首帧保持;
- 循环模式自动禁用并重置 Spine 骨骼跟随和路径跟随;
- 修复循环重新计算期间缓存帧与实时状态交替造成的闪烁;
- 时间轴支持选择包含结束端点的最后一帧;
- 多粒子系统独立计算,整体时间轴继续取粒子和 Spine 中最长者;
- 完成 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
有效范围为 1~120 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 启动段
启动段规则:
- 第一帧完全为空;
- 粒子骨骼数量为 0;
- 延迟期间保持空帧;
- 延迟结束后开始正常生成粒子;
- 粒子使用正常生命周期,可以在启动过程中死亡;
- 系统自然预热到稳定循环状态;
- 最后一帧到达循环衔接状态。
当最大粒子寿命跨越多个循环周期时,启动段会自动使用足够的预热周期,保证末端确实进入稳定循环分布。
4.4 纯循环段
纯循环段规则:
- 延迟期间保持循环衔接帧;
- 延迟结束后播放一个完整循环周期;
- 周期长度由
loopDurationFrames决定; - 发射事件、随机参数和资源选择在每个周期使用相同确定性序列;
- 周期末端由真实模拟自然到达下一周期起点;
- 不再把末帧强制替换为首帧。
这一实现保证的不只是边界两个快照一致,还保证倒数帧到结束端点、结束端点到下一周期的运动连续,不会在最后两帧突然跳变或卡顿。
4.5 结束段
结束段规则:
- 第一帧为循环衔接状态;
- 延迟期间保持该衔接状态;
- 延迟结束后立即停止生成新粒子;
- 已存在粒子继续按正常生命周期运行;
- 拖尾随粒子继续更新;
- 最后一帧所有粒子和拖尾消失。
结束段不使用发射时长作为消亡长度。长度根据衔接帧中粒子的最大剩余生命和拖尾状态自动计算。
五、稳定循环计算
5.1 完整周期预演
早期实现只把纯循环末帧复制为首帧。该方式虽然能让两个快照数值相同,却会使倒数帧直接跳到衔接状态,造成明显卡顿。
当前流程改为:
- 根据循环时长计算每周期帧数;
- 根据最大粒子寿命计算需要预演的周期数;
- 从确定性随机种子开始模拟;
- 每个新周期重置发射计时和随机序列;
- 保留跨周期仍存活粒子的物理状态;
- 预演到粒子分布稳定;
- 记录下一完整周期及结束端点;
- 时间轴循环时直接回放缓存结果。
5.2 周期随机序列
每个周期重新开始:
- 发射累计器;
- 发射计时;
- 粒子生成序号;
- 全局随机源;
- 与发射周期相关的吸附计时。
仍存活粒子不会在周期边界被重置,其运动会继续自然推进。
噪声相位、拖尾资源采样和吸附曲线方向改为使用周期内粒子生成序号,不再依赖粒子池槽位。即使粒子池复用了不同编号,也不会改变下一周期相同发射事件的视觉属性。
5.3 假死粒子
纯循环段需要保持粒子骨骼集合稳定。某粒子在某些帧已按正常生命周期死亡时,录制缓存不会直接删除对应骨骼,而是写入假死状态:
active = true
alpha = 0
imageVisible = false
trailState = undefined
因此:
- 视觉上粒子已经死亡;
- 图片和拖尾均不可见;
- 逻辑上粒子骨骼仍存在;
- 周期内不会因为骨骼突然增删破坏衔接;
- 后续正常出现时仍可继续使用同一骨骼轨道。
假死只用于纯循环段。启动段和结束段仍使用正常粒子死亡逻辑。
5.4 缓存帧闪烁修复
循环段会在录制首帧一次性生成完整缓存。此前在全局时间轴第一次录制结束前,固定帧之间仍会调用 update(0) 显示粒子内部实时状态,导致画面在以下两套状态之间交替:
- 已计算好的循环缓存帧;
- 周期预演结束后的内部状态。
表现为重新计算后粒子高频闪烁,直到时间轴完整运行一遍才恢复。
当前逻辑在循环缓存存在后立即全程读取缓存,不再夹杂实时状态。
六、延迟时间
循环持续继续使用原“延迟时间”参数,三种状态均支持。
| 状态 | 延迟期间保持内容 |
|---|---|
| 启动段 | 空的第一帧 |
| 纯循环段 | 循环衔接帧 |
| 结束段 | 循环衔接帧 |
延迟结束后才开始推进对应动画。
时间轴中:
- 粒子条左侧位置继续表示延迟;
- 可以拖动粒子条调整延迟;
- 整体播放长度包含延迟帧;
- 延迟期间画布不是重复重新计算,而是保持第一帧缓存。
七、跟随功能限制
循环持续不与 Spine 骨骼跟随或路径跟随联动。原因是外部目标动画或路径进度可能不具备相同周期,无法保证粒子周期边界稳定。
进入或退出循环持续时均弹出提示:
粒子跟随设置会失效并恢复默认值
只有用户确认后才切换。
确认后重置:
- 发射器跟随总开关;
- 跟随模式;
- 路径 ID;
- Spine ID 与骨骼名;
- 跟随空间和方向;
- 路径进度曲线;
- 位移、旋转和缩放偏移。
循环持续期间跟随控件不可重新开启。切回常规持续后控件恢复可用,但不会自动恢复进入循环前的旧跟随设置。
八、时间轴规则
8.1 结束端点
时间轴内部保存的是快照数量,界面显示的是最后一个可选帧编号。
例如动画长度为 54f:
可选帧:0f~54f
快照数量: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 错误;
- 无构建错误;
- 仅保留既有的大包体积提示。
交互修复过程中已覆盖:
- 循环时长与常规持续时长独立;
- 纯循环末端不再硬复制首帧;
- 延迟期间保持第一帧;
- 时间轴可以到达结束端点;
- 重新计算期间不再交替显示内部实时状态;
- 配置字段具备旧数据迁移默认值。
十二、阶段十最终状态
阶段十完成后,编辑器已经具备:
- 单图和序列帧混合资源;
- 多种序列播放方式;
- 确定性粒子序列帧录制;
- 常规持续与独立循环持续;
- 启动、循环、结束三段动画生成;
- 稳定周期预演;
- 假死粒子骨骼保持;
- 延迟首帧保持;
- 多系统时间轴对齐;
- 配置、预设、复制和撤回联动。
至此,阶段十“序列帧资源与循环持续动画体系”完成落盘。