# 网页粒子系统 · 阶段四 > 阶段定位:**修改器模块第一阶段定版** > 完成日期:2026-08-28 > 工程目录:`/Users/tianmokeji/Desktop/SpineParticle` > 技术栈:Vue 3 + TypeScript + Pinia + PixiJS 7 + Vite --- ## 一、阶段结论 阶段四围绕粒子系统的外部运动影响完成开发,已经实现并接入实时预览的修改器包括: 1. 移动噪声; 2. 重力; 3. 风力; 4. 全局力场; 5. 吸附。 本阶段同时统一了场景初始状态和随机种子语义:打开项目时默认创建一个粒子系统,仅展开“场景对象”模块,其他模块保持折叠;所有修改器默认关闭。随机种子移动到场景对象模块,作为粒子系统全局随机入口,相同种子能够复现随机初始属性、资源选择和修改器采样结果。 阶段四结束后,项目已经具备“基础发射参数 + 外观资源 + 生命周期属性 + 多种运动修改器 + 画布辅助交互”的完整实时编辑链路。 --- ## 二、初始状态与全局随机种子 ### 2.1 默认场景状态 - 场景中默认创建一个名为 `ParticleSystem1` 的粒子系统; - “场景对象”模块默认展开; - 发射、形状、粒子属性、外观资源、修改器和导出等模块默认折叠; - 移动噪声、重力、风力、力场和吸附默认关闭; - 原有粒子属性、外观资源和时间轴功能保持不变。 ### 2.2 随机种子 随机种子从“粒子属性”移动到“场景对象”,其影响范围扩展为整个粒子系统: - 初始生命周期、速度、缩放和旋转的随机采样; - 图片资源的随机选择; - 重力和风力的粒子级随机强度; - 移动噪声的粒子相位; - 曲线吸附的弯曲方向。 包括 `0` 在内的任意整数种子都使用确定性随机序列。重新模拟相同配置时,可以获得一致的粒子结果。 --- ## 三、移动噪声 移动噪声用于在不破坏基础物理轨迹的前提下,为粒子增加连续的视觉偏移。 | 参数 | 默认值 | 作用 | |---|---:|---| | 强度 | 30 | 控制噪声影响比例,范围 0~100% | | 波动范围 | 100 | 控制粒子偏离原轨迹的最大范围 | | 时间流速 | 1 | 控制噪声随时间变化的速度 | 实现规则: - 噪声只作用于最终渲染位置,粒子的基础 `x/y` 和速度仍由物理系统维护; - 每个粒子使用由全局种子和粒子池编号推导的独立相位; - 出生时减去初始噪声采样,保证粒子仍从原发射点出现; - 使用连续正弦变化避免逐帧随机产生的跳动; - 反复关闭、开启且参数和种子相同时,轨迹保持可复现。 --- ## 四、重力 重力支持固定强度、粒子级随机强度、方向和生命周期曲线。 ### 4.1 默认值与方向 | 参数 | 默认值 | |---|---:| | 模式 | 固定 | | 重力强度 | 980 | | 方向 | -90° | | 生命周期曲线 | 全程 1 | 方向使用数学角度: - `0°`:向右; - `-90°`:向屏幕下方; - 正强度沿设定方向作用; - 负强度使作用方向反转。 ### 4.2 固定与随机 - 固定模式下,全部粒子使用当前固定强度; - 随机模式下,每个粒子出生时在 `min~max` 中独立采样; - 随机结果受全局随机种子控制; - 已出生粒子的随机强度保持不变。 ### 4.3 生命周期内重力 生命周期曲线的横轴为归一化生命时间 `0~1`,纵轴为重力倍率 `0~1`。最终重力为: ```text 最终重力 = 粒子重力强度 × 生命周期曲线倍率 ``` 曲线支持关键点编辑和恢复默认水平曲线。 --- ## 五、风力 风力复用重力的模式结构和生命周期曲线,但使用独立配置。 | 参数 | 默认值 | |---|---:| | 模式 | 固定 | | 风力强度 | 100 | | 方向 | 0°,水平向右 | | 生命周期曲线 | 全程 1 | 风力同样支持: - 固定强度; - 每个粒子独立的随机强度范围; - `0°` 向右、`-90°` 向下的数学角度规则; - 负强度反转方向; - 生命周期 `0~1` 倍率曲线; - 全局随机种子复现。 --- ## 六、全局力场 力场以场景全局坐标定义,不跟随粒子系统自身的位移、旋转和缩放。 ### 6.1 参数 | 参数 | 默认值 | 说明 | |---|---:|---| | 中心 X/Y | 0 / 0 | 场景全局数学坐标 | | 力场强度 | 10 | 正数吸引,负数排斥 | | 力场半径 | 100 | 力场作用范围 | | 衰减模式 | 线性衰减 | 边缘强度为 0 | ### 6.2 衰减模式 1. **恒定**:半径范围内力度不变; 2. **线性衰减**:中心最强,接近边缘时线性下降为 0; 3. **距离反比**:距离中心越近力度越强,并设置中心上限以避免数值爆炸。 ### 6.3 坐标与物理计算 每帧先将粒子从发射器局部坐标转换为场景全局数学坐标,计算力场加速度,再将加速度转换回粒子系统局部坐标。因此: - 力场中心始终位于固定的场景位置; - 粒子系统经过位移、旋转或非等比缩放后,力场方向仍正确; - 正强度始终把粒子拉向中心; - 负强度始终把粒子推离中心。 ### 6.4 画布交互 - 开启后在画布显示力场作用圆和中心标记; - 正吸力使用蓝色,负斥力使用红色; - 按住圆内任意位置即可拖动力场中心; - 拖动结果实时同步到面板中心 X/Y; - 圆形辅助线使用全局坐标,不应用粒子系统根变换。 --- ## 七、吸附 吸附用于在延迟结束后,把粒子从当时所在位置移动到指定全局点;粒子进入吸附完成半径后立即死亡。 ### 7.1 默认参数 | 参数 | 默认值 | 说明 | |---|---:|---| | 吸附点 X | 200 | 场景全局数学坐标 | | 吸附点 Y | 0 | 场景全局数学坐标 | | 吸附半径 | 20 | 进入范围即视为完成并死亡 | | 吸附时长 | 0.5 秒 | 从当前点移动到吸附点的时间 | | 延迟时间 | 0.1 秒 | 延迟结束后开始受吸附影响 | | 延迟方式 | 单粒子生命 | 每个粒子按出生时间独立计时 | | 吸附方式 | 曲线 | 使用确定性的二次曲线路径 | 吸附模块默认关闭。 ### 7.2 延迟方式 | 模式 | 行为 | |---|---| | 统一时间 | 从吸附开关开启时统一计时;延迟结束后,当前及之后的粒子立即具备吸附条件 | | 单粒子生命 | 每个粒子从出生开始独立计时,达到延迟时间后才开始吸附 | ### 7.3 吸附路径 - **直线**:从吸附开始时的位置匀速插值到吸附点; - **曲线**:使用二次贝塞尔曲线移动,曲线弯曲方向由全局种子和粒子编号确定; - 吸附开始时记录粒子的实际当前位置,不会跳回出生点; - 拖动画布上的吸附点时,正在吸附的粒子会继续朝新的目标位置移动。 ### 7.4 死亡规则 粒子在以下任一条件先满足时死亡: 1. 进入吸附半径; 2. 吸附路径进度达到终点; 3. 粒子自身生命周期耗尽。 生命周期判断优先于吸附计算,因此吸附不会延长粒子原本的生命。吸附半径可设为 `0`,此时目标表示一个点,粒子到达中心后死亡。 ### 7.5 画布交互 - 开启后在画布显示红色吸附圆和中心十字; - 半径为 `0` 时显示红色中心点; - 可按住吸附圆拖动全局位置; - 半径为 `0` 时仍保留约 12 像素的鼠标命中区域,便于拖动; - 拖动结果实时同步到面板吸附点 X/Y; - 吸附圆与力场圆重叠时,红色吸附圆优先接收拖动。 --- ## 八、修改器执行顺序 当前单帧主要执行顺序为: 1. 扣除粒子自身生命周期,生命耗尽则立即销毁; 2. 计算重力; 3. 计算风力; 4. 计算全局力场; 5. 应用阻尼; 6. 积分基础位置; 7. 判断吸附延迟并覆盖吸附路径位置; 8. 计算移动噪声的渲染偏移; 9. 更新缩放、旋转、透明度、颜色和混合模式; 10. 生成实时状态或录制帧。 吸附开始后位置由吸附路径控制,并清除原速度,避免外力积累造成终点抖动。移动噪声仍属于渲染偏移,不改变吸附和物理系统维护的基础坐标。 --- ## 九、核心实现文件 | 文件 | 本阶段职责 | |---|---| | `src/core/particleEmitter.ts` | 修改器配置、默认值、配置补齐、随机采样、重力/风力/力场/吸附/噪声计算 | | `src/views/ParticlePanel.vue` | 修改器开关、参数控件、模式选择与生命周期曲线 | | `src/views/Stage.vue` | 全局力场和吸附范围绘制、画布拖动、坐标换算及实时预览 | | `src/store/particleStore.ts` | 默认粒子系统和编辑器状态的承载 | 为兼容热更新对象和旧配置,`ensureEmitterConfig()` 会自动补齐新增字段。旧版重力、二维风力和力场参数也保留迁移处理。 --- ## 十、验证结果 本阶段已完成以下检查: - 相同种子下移动噪声重复开启可得到一致结果; - 重力方向 `0°` 向右、`-90°` 向下; - 重力和风力固定/随机模式能正确切换; - 生命周期倍率曲线已参与重力和风力计算; - 力场三种衰减模式可切换且配置实时生效; - 力场圆画布拖动与面板坐标同步; - 吸附默认参数、延迟模式、路径模式、死亡优先级均已接入运行逻辑; - `npm run build` 通过; - `git diff --check` 通过。 Vite 仍会提示主包体积超过 500 kB,该提示不影响当前功能运行。 --- ## 十一、当前边界与已知风险 1. **拖尾尚未实现**:当前只有配置开关,没有轨迹采样和渲染逻辑。 2. **碰撞尚未实现**:界面仍标记为预留,未定义碰撞体和反弹规则。 3. **路径跟随尚未实现**:界面仍标记为预留,尚未建立路径编辑和粒子约束。 4. **修改器组合缺少系统测试**:重力、风力、力场、吸附和噪声同时开启时,需要补充参数极值和稳定性测试。 5. **吸附曲线暂为自动弧线**:当前不能由用户编辑控制点,也没有自定义吸附曲线编辑器。 6. **辅助圆没有独立显示开关**:开启力场或吸附后,选中系统时始终显示对应辅助范围。 7. **工程保存/加载尚未完成**:新增修改器字段目前依赖内存配置和默认值,尚未形成正式版本化工程格式。 8. **缺少自动化单元测试**:当前主要依赖类型检查、生产构建和人工交互验证。 --- ## 十二、下一步开发建议 ### 优先级 P0:修改器模块收尾 建议按以下顺序继续,避免同时扩散多个高成本功能: 1. 拖尾:确定每粒子采样点上限、宽度/颜色/透明度生命周期和对象池; 2. 碰撞:先支持全局直线、矩形和圆形碰撞体,再扩展反弹、摩擦和死亡; 3. 路径跟随:复用吸附的全局坐标与曲线求值,增加可编辑路径控制点; 4. 增加修改器总开关、辅助线显示开关和单项重置。 ### 优先级 P1:工程保存与加载 - 定义 `ProjectSchema` 和 `schemaVersion`; - 将 Pixi 运行时对象与可序列化参数分离; - 保存全部修改器开关、模式、曲线和全局坐标; - 为阶段三、阶段四配置建立明确迁移函数; - 支持工程 JSON 或包含资源的 ZIP 工程包。 ### 优先级 P2:修改器组合测试 - 为全局/局部坐标转换增加单元测试; - 验证旋转、负缩放、非等比缩放下的力场和吸附; - 测试极短生命周期、零延迟、零半径和极短吸附时长; - 测试正负极值、帧率波动和大粒子数量; - 固化相同种子的轨迹快照,防止随机语义回归。 ### 优先级 P3:交互与可视化 - 力场和吸附中心增加悬停、选中和拖动反馈; - 为圆形辅助线增加半径拖拽手柄; - 在画布标注半径、强度方向和中心坐标; - 增加修改器辅助线显隐入口; - 处理力场、吸附点、根变换 Gizmo 重叠时的明确选中规则。 ### 优先级 P4:性能与导出准备 - 避免每帧重复查找资源配置; - 为多个全局力场或碰撞体预留空间索引; - 明确修改器结果在固定帧录制中的采样精度; - 验证吸附死亡对粒子骨骼池和导出帧的影响; - 对 400 粒子上限进行组合修改器性能压测。 --- ## 十三、阶段四验收标准 阶段四可视为完成,当以下条件持续满足: - 默认场景和模块折叠状态符合约定; - 所有已实现修改器默认关闭; - 移动噪声受全局随机种子控制且可复现; - 重力和风力的固定、随机、方向与生命周期曲线真实生效; - 力场使用全局坐标并支持吸力、斥力、三种衰减和画布拖动; - 吸附支持全局点、完成半径、时长、两种延迟方式、两种路径和画布拖动; - 粒子进入吸附范围或自身生命周期结束时能够正确销毁; - 阶段三已经完成的粒子属性与外观资源功能没有发生回归; - TypeScript 类型检查和生产构建保持通过。