@fps-games/vfx 0.3.2 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/package.json +5 -4
- package/tooling/vfx-cli.mjs +8 -1
- package/docs/AUTHORING_EFFECTS.md +0 -297
- package/docs/INTEGRATION.md +0 -194
- package/docs/VFX_LIBRARY_ARCHITECTURE_chatgpt.md +0 -1580
- package/docs/VFX_LIBRARY_EXECUTION_PLAN.md +0 -229
- package/docs/VFX_LIBRARY_PLAN.md +0 -546
- package/docs/hit-flash-red-method.md +0 -155
- package/docs/treasure_attention_fx_babylonjs_guide.md +0 -901
- package/docs/vfx-ab/RESULTS.md +0 -35
- package/docs/vfx-ab/lumber-order/vehicle-exhaust-smoke/after.png +0 -0
- package/docs/vfx-ab/lumber-order/vehicle-exhaust-smoke/before.png +0 -0
- package/docs/vfx-ab/lumber-truck/vehicle-exhaust-smoke/after.png +0 -0
- package/docs/vfx-ab/lumber-truck/vehicle-exhaust-smoke/before.png +0 -0
- package/docs/vfx-integration_chatgpt.md +0 -462
- package/docs/vfx-placement-design.md +0 -164
- package/docs/weapon-trail-visualization.html +0 -241
- package/packages/EffectPackageService.ts +0 -346
- package/packages/SceneVfxService.ts +0 -96
- package/packages/build.mesh.yellow_build_upgrade_indicator/assets/runtime/simpleMeshEffect.v1.js +0 -333
- package/packages/build.mesh.yellow_build_upgrade_indicator/assets/shaders/mesh-effect-preview.frag.glsl +0 -25
- package/packages/build.mesh.yellow_build_upgrade_indicator/assets/shaders/mesh-effect-preview.vert.glsl +0 -11
- package/packages/build.mesh.yellow_build_upgrade_indicator/assets/textures/effect_jianbian.png +0 -0
- package/packages/build.mesh.yellow_build_upgrade_indicator/effect.json +0 -927
- package/packages/build.mesh.yellow_build_upgrade_indicator/media/contact-sheet.png +0 -0
- package/packages/build.mesh.yellow_build_upgrade_indicator/media/preview.gif +0 -0
- package/packages/build.mesh.yellow_build_upgrade_indicator/media/preview.mp4 +0 -0
- package/packages/build.mesh.yellow_build_upgrade_indicator/media/preview.webm +0 -0
- package/packages/build.mesh.yellow_build_upgrade_indicator/media/thumbnail.png +0 -0
- package/packages/build.mesh.yellow_build_upgrade_indicator/metadata/description.json +0 -197
- package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/03-effect.original.json +0 -895
- package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/03-normalized-vfx-to-babylon-report.json +0 -241
- package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/04-preview-overrides.json +0 -542
- package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/04-preview-tuning-report.json +0 -69
- package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/asset-map.json +0 -125
- package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/lineage.json +0 -44
- package/packages/build.particle.golden_upgrade_starburst/assets/runtime/particleEmitter.v1.js +0 -210
- package/packages/build.particle.golden_upgrade_starburst/assets/textures/effect_guangdian.png +0 -0
- package/packages/build.particle.golden_upgrade_starburst/effect.json +0 -880
- package/packages/build.particle.golden_upgrade_starburst/media/contact-sheet.png +0 -0
- package/packages/build.particle.golden_upgrade_starburst/media/preview.gif +0 -0
- package/packages/build.particle.golden_upgrade_starburst/media/preview.mp4 +0 -0
- package/packages/build.particle.golden_upgrade_starburst/media/preview.webm +0 -0
- package/packages/build.particle.golden_upgrade_starburst/media/thumbnail.png +0 -0
- package/packages/build.particle.golden_upgrade_starburst/metadata/description.json +0 -161
- package/packages/build.particle.golden_upgrade_starburst/provenance/03-effect.original.json +0 -762
- package/packages/build.particle.golden_upgrade_starburst/provenance/03-normalized-vfx-to-babylon-report.json +0 -260
- package/packages/build.particle.golden_upgrade_starburst/provenance/04-preview-overrides.json +0 -436
- package/packages/build.particle.golden_upgrade_starburst/provenance/04-preview-tuning-report.json +0 -40
- package/packages/build.particle.golden_upgrade_starburst/provenance/asset-map.json +0 -115
- package/packages/build.particle.golden_upgrade_starburst/provenance/lineage.json +0 -40
- package/packages/build.particle.orange_upgrade_transform_sparks/assets/runtime/particleEmitter.v1.js +0 -210
- package/packages/build.particle.orange_upgrade_transform_sparks/assets/textures/b5b27ab1-e740-4398-b407-848fc2b2c897.png +0 -0
- package/packages/build.particle.orange_upgrade_transform_sparks/effect.json +0 -887
- package/packages/build.particle.orange_upgrade_transform_sparks/media/preview.gif +0 -0
- package/packages/build.particle.orange_upgrade_transform_sparks/media/preview.mp4 +0 -0
- package/packages/build.particle.orange_upgrade_transform_sparks/media/preview.webm +0 -0
- package/packages/build.particle.orange_upgrade_transform_sparks/media/thumbnail.png +0 -0
- package/packages/build.particle.orange_upgrade_transform_sparks/metadata/description.json +0 -179
- package/packages/build.particle.orange_upgrade_transform_sparks/provenance/03-effect.original.json +0 -859
- package/packages/build.particle.orange_upgrade_transform_sparks/provenance/03-normalized-vfx-to-babylon-report.json +0 -260
- package/packages/build.particle.orange_upgrade_transform_sparks/provenance/04-preview-overrides.json +0 -478
- package/packages/build.particle.orange_upgrade_transform_sparks/provenance/04-preview-tuning-report.json +0 -40
- package/packages/build.particle.orange_upgrade_transform_sparks/provenance/asset-map.json +0 -114
- package/packages/build.particle.orange_upgrade_transform_sparks/provenance/lineage.json +0 -41
- package/packages/build.particle.wood_chip_dust_burst/assets/runtime/particleEmitter.v1.js +0 -210
- package/packages/build.particle.wood_chip_dust_burst/assets/textures/effect_yanwu4.png +0 -0
- package/packages/build.particle.wood_chip_dust_burst/assets/textures/suipian3.png +0 -0
- package/packages/build.particle.wood_chip_dust_burst/effect.json +0 -1400
- package/packages/build.particle.wood_chip_dust_burst/media/contact-sheet.png +0 -0
- package/packages/build.particle.wood_chip_dust_burst/media/preview.gif +0 -0
- package/packages/build.particle.wood_chip_dust_burst/media/preview.mp4 +0 -0
- package/packages/build.particle.wood_chip_dust_burst/media/preview.webm +0 -0
- package/packages/build.particle.wood_chip_dust_burst/media/thumbnail.png +0 -0
- package/packages/build.particle.wood_chip_dust_burst/metadata/description.json +0 -173
- package/packages/build.particle.wood_chip_dust_burst/provenance/03-effect.original.json +0 -1277
- package/packages/build.particle.wood_chip_dust_burst/provenance/03-normalized-vfx-to-babylon-report.json +0 -329
- package/packages/build.particle.wood_chip_dust_burst/provenance/04-preview-overrides.json +0 -749
- package/packages/build.particle.wood_chip_dust_burst/provenance/04-preview-tuning-report.json +0 -60
- package/packages/build.particle.wood_chip_dust_burst/provenance/asset-map.json +0 -146
- package/packages/build.particle.wood_chip_dust_burst/provenance/lineage.json +0 -69
- package/packages/effects/building-upgrade/effect.json +0 -6
- package/packages/effects/building-upgrade/index.ts +0 -387
- package/packages/effects/character-entrance/effect.json +0 -6
- package/packages/effects/character-entrance/index.ts +0 -308
- package/packages/effects/coin-burst/index.ts +0 -48
- package/packages/effects/comet-trail-flame/assets/textures/trail_5x4.webp +0 -0
- package/packages/effects/comet-trail-flame/index.ts +0 -107
- package/packages/effects/conveyor-upgrade/effect.json +0 -6
- package/packages/effects/conveyor-upgrade/index.ts +0 -401
- package/packages/effects/debris-smoke/assets/models/rock_debris.glb +0 -0
- package/packages/effects/debris-smoke/assets/textures/smoke22.webp +0 -0
- package/packages/effects/debris-smoke/index.ts +0 -102
- package/packages/effects/door_open_gold_flakes/assets/runtime/goldFlakes.v1.js +0 -397
- package/packages/effects/door_open_gold_flakes/door_open_gold_flakes.json +0 -498
- package/packages/effects/door_open_gold_flakes/index.ts +0 -11
- package/packages/effects/electric-arc/assets/textures/spark_4x4.webp +0 -0
- package/packages/effects/electric-arc/index.ts +0 -63
- package/packages/effects/energy-shield/effect.json +0 -7
- package/packages/effects/energy-shield/index.ts +0 -432
- package/packages/effects/explosion/assets/textures/baozha29.webp +0 -0
- package/packages/effects/explosion/assets/textures/glow01.webp +0 -0
- package/packages/effects/explosion/assets/textures/lizi01.webp +0 -0
- package/packages/effects/explosion/assets/textures/xulie_lizibaozha02_5x5.webp +0 -0
- package/packages/effects/explosion/index.ts +0 -115
- package/packages/effects/ground-tile-upgrade/effect.json +0 -6
- package/packages/effects/ground-tile-upgrade/index.ts +0 -410
- package/packages/effects/hit-flash/index.ts +0 -77
- package/packages/effects/laser-beam/assets/textures/laser_glow.webp +0 -0
- package/packages/effects/laser-beam/assets/textures/laser_noise.webp +0 -0
- package/packages/effects/laser-beam/index.ts +0 -6
- package/packages/effects/laser-beam-factory.ts +0 -146
- package/packages/effects/lumber-cart-suction/effect.json +0 -6
- package/packages/effects/lumber-cart-suction/index.ts +0 -399
- package/packages/effects/lumber-debris-scatter/assets/models/lumber_prop_model.glb +0 -0
- package/packages/effects/lumber-debris-scatter/assets/models/lumber_prop_model.glb.versions/.active +0 -1
- package/packages/effects/lumber-debris-scatter/assets/models/lumber_prop_model.glb.versions/1781589063890_upload.glb +0 -0
- package/packages/effects/lumber-debris-scatter/assets/runtime/solidParticleScatter.v1.js +0 -236
- package/packages/effects/lumber-debris-scatter/effect.json +0 -228
- package/packages/effects/lumber-debris-scatter/index.ts +0 -780
- package/packages/effects/lumber_vehicle_gear_spin/assets/runtime/gearSpin.v1.js +0 -202
- package/packages/effects/lumber_vehicle_gear_spin/index.ts +0 -11
- package/packages/effects/lumber_vehicle_gear_spin/lumber_vehicle_gear_spin.json +0 -338
- package/packages/effects/lumber_vehicle_upgrade_aura/assets/runtime/upgradeAura.v1.js +0 -353
- package/packages/effects/lumber_vehicle_upgrade_aura/index.ts +0 -13
- package/packages/effects/lumber_vehicle_upgrade_aura/lumber_vehicle_upgrade_aura.json +0 -365
- package/packages/effects/lumber_vehicle_wood_chips/assets/runtime/solidParticleScatter.v1.js +0 -310
- package/packages/effects/lumber_vehicle_wood_chips/index.ts +0 -11
- package/packages/effects/lumber_vehicle_wood_chips/lumber_vehicle_wood_chips.json +0 -335
- package/packages/effects/monster-hit/index.ts +0 -129
- package/packages/effects/player-upgrade/effect.json +0 -6
- package/packages/effects/player-upgrade/index.ts +0 -640
- package/packages/effects/pulse-laser-volley/assets/textures/bolt_guangshu.webp +0 -0
- package/packages/effects/pulse-laser-volley/index.ts +0 -215
- package/packages/effects/resource-collect-sparkles/effect.json +0 -6
- package/packages/effects/resource-collect-sparkles/index.ts +0 -254
- package/packages/effects/run-footstep-dust/assets/runtime/runFootstepDust.v1.js +0 -215
- package/packages/effects/run-footstep-dust/effect.json +0 -183
- package/packages/effects/run-footstep-dust/index.ts +0 -377
- package/packages/effects/space-shared.ts +0 -120
- package/packages/effects/thruster-flame/index.ts +0 -306
- package/packages/effects/treasure-attention/effect.json +0 -7
- package/packages/effects/treasure-attention/index.ts +0 -630
- package/packages/effects/tree-chop-dust/assets/textures/tree_chop_dust_atlas.png +0 -0
- package/packages/effects/tree-chop-dust/effect.json +0 -8
- package/packages/effects/tree-chop-dust/index.ts +0 -202
- package/packages/effects/tree-leaf-chop-burst/assets/runtime/particleEmitter.v1.js +0 -303
- package/packages/effects/tree-leaf-chop-burst/assets/textures/tree_leaf_chop_burst_leaf_atlas.png +0 -0
- package/packages/effects/tree-leaf-chop-burst/effect.json +0 -498
- package/packages/effects/tree-leaf-chop-burst/index.ts +0 -294
- package/packages/effects/tree_chop_dust_burst/assets/runtime/particleEmitter.v1.js +0 -318
- package/packages/effects/tree_chop_dust_burst/assets/textures/tree_chop_dust_burst_dust.png +0 -0
- package/packages/effects/tree_chop_dust_burst/index.ts +0 -13
- package/packages/effects/tree_chop_dust_burst/tree_chop_dust_burst.json +0 -412
- package/packages/effects/ufo-thread-flame/assets/textures/flame_flow.webp +0 -0
- package/packages/effects/ufo-thread-flame/assets/textures/flame_spike.webp +0 -0
- package/packages/effects/ufo-thread-flame/index.ts +0 -153
- package/packages/effects/vehicle-exhaust-smoke/assets/textures/vehicle_exhaust_smoke_atlas.png +0 -0
- package/packages/effects/vehicle-exhaust-smoke/effect.json +0 -8
- package/packages/effects/vehicle-exhaust-smoke/index.ts +0 -298
- package/packages/effects/vehicle-upgrade/effect.json +0 -6
- package/packages/effects/vehicle-upgrade/index.ts +0 -404
- package/packages/effects/weapon-trail/assets/textures/trail_wedge.png +0 -0
- package/packages/effects/weapon-trail/index.ts +0 -317
- package/packages/effects/wood-crusher-sawdust/assets/runtime/particleEmitter.v1.js +0 -312
- package/packages/effects/wood-crusher-sawdust/assets/textures/wood_crusher_sawdust_dust.png +0 -0
- package/packages/effects/wood-crusher-sawdust/assets/textures/wood_crusher_sawdust_fiber.png +0 -0
- package/packages/effects/wood-crusher-sawdust/index.ts +0 -43
- package/packages/effects/wood-crusher-sawdust/wood_crusher_sawdust.json +0 -592
- package/packages/effects/wood-cutter-sawdust/assets/runtime/particleEmitter.v1.js +0 -312
- package/packages/effects/wood-cutter-sawdust/assets/textures/wood_cutter_sawdust_chip.png +0 -0
- package/packages/effects/wood-cutter-sawdust/assets/textures/wood_cutter_sawdust_dust.png +0 -0
- package/packages/effects/wood-cutter-sawdust/index.ts +0 -43
- package/packages/effects/wood-cutter-sawdust/wood_cutter_sawdust.json +0 -592
- package/packages/effects/wood-sawdust-effect-factory.ts +0 -194
- package/packages/effects/wood_crusher_sawdust/assets/runtime/particleEmitter.v1.js +0 -318
- package/packages/effects/wood_crusher_sawdust/assets/textures/wood_crusher_sawdust_dust.png +0 -0
- package/packages/effects/wood_crusher_sawdust/assets/textures/wood_crusher_sawdust_fiber.png +0 -0
- package/packages/effects/wood_crusher_sawdust/index.ts +0 -29
- package/packages/effects/wood_crusher_sawdust/wood_crusher_sawdust.json +0 -592
- package/packages/effects/wood_cutter_sawdust/assets/runtime/particleEmitter.v1.js +0 -318
- package/packages/effects/wood_cutter_sawdust/assets/textures/wood_cutter_sawdust_chip.png +0 -0
- package/packages/effects/wood_cutter_sawdust/assets/textures/wood_cutter_sawdust_dust.png +0 -0
- package/packages/effects/wood_cutter_sawdust/index.ts +0 -29
- package/packages/effects/wood_cutter_sawdust/wood_cutter_sawdust.json +0 -592
- package/packages/effects/wood_peel_material_test/assets/runtime/woodPeelMaterialTest.v1.js +0 -196
- package/packages/effects/wood_peel_material_test/index.ts +0 -11
- package/packages/effects/wood_peel_material_test/wood_peel_material_test.json +0 -136
- package/packages/env.particle.forest_edge_fog/assets/runtime/particleEmitter.v1.js +0 -210
- package/packages/env.particle.forest_edge_fog/assets/textures/f12a23c4-b924-4322-a260-3d982428f1e8.png +0 -0
- package/packages/env.particle.forest_edge_fog/assets/textures/yuan.png +0 -0
- package/packages/env.particle.forest_edge_fog/effect.json +0 -854
- package/packages/env.particle.forest_edge_fog/media/preview.gif +0 -0
- package/packages/env.particle.forest_edge_fog/media/preview.mp4 +0 -0
- package/packages/env.particle.forest_edge_fog/media/preview.webm +0 -0
- package/packages/env.particle.forest_edge_fog/media/thumbnail.png +0 -0
- package/packages/env.particle.forest_edge_fog/metadata/description.json +0 -148
- package/packages/env.particle.forest_edge_fog/provenance/03-effect.original.json +0 -827
- package/packages/env.particle.forest_edge_fog/provenance/03-normalized-vfx-to-babylon-report.json +0 -196
- package/packages/env.particle.forest_edge_fog/provenance/04-preview-overrides.json +0 -432
- package/packages/env.particle.forest_edge_fog/provenance/04-preview-tuning-report.json +0 -28
- package/packages/env.particle.forest_edge_fog/provenance/asset-map.json +0 -124
- package/packages/env.particle.forest_edge_fog/provenance/lineage.json +0 -41
- package/packages/generation.ts +0 -14
- package/packages/index.ts +0 -14
- package/packages/legacy-particle-runtime.ts +0 -113
- package/packages/manifestRuntimePackage.ts +0 -519
- package/packages/registry.ts +0 -85
- package/packages/rendering.ts +0 -13
- package/packages/resource.particle.viscous_oil_suction/assets/runtime/top_disk_suction/particleEmitter.v1.js +0 -424
- package/packages/resource.particle.viscous_oil_suction/assets/textures/Glow ad.png +0 -0
- package/packages/resource.particle.viscous_oil_suction/effect.json +0 -1254
- package/packages/resource.particle.viscous_oil_suction/media/preview.gif +0 -0
- package/packages/resource.particle.viscous_oil_suction/media/preview.mp4 +0 -0
- package/packages/resource.particle.viscous_oil_suction/media/preview.webm +0 -0
- package/packages/resource.particle.viscous_oil_suction/media/thumbnail.png +0 -0
- package/packages/resource.particle.viscous_oil_suction/metadata/description.json +0 -122
- package/packages/resource.particle.viscous_oil_suction/provenance/03-effect.original.json +0 -1051
- package/packages/resource.particle.viscous_oil_suction/provenance/03-normalized-vfx-to-babylon-report.json +0 -200
- package/packages/resource.particle.viscous_oil_suction/provenance/04-preview-overrides.json +0 -581
- package/packages/resource.particle.viscous_oil_suction/provenance/04-preview-tuning-report.json +0 -28
- package/packages/resource.particle.viscous_oil_suction/provenance/asset-map.json +0 -111
- package/packages/resource.particle.viscous_oil_suction/provenance/lineage.json +0 -45
- package/packages/types.ts +0 -195
- package/tooling/check-dist-runtime.mjs +0 -166
- package/tooling/generate-index.mjs +0 -55
- package/tooling/test-guardrails.mjs +0 -157
- package/tooling/validate-boundary.mjs +0 -92
- package/tooling/validate-effects.mjs +0 -304
- package/tooling/validate.mjs +0 -53
package/docs/VFX_LIBRARY_PLAN.md
DELETED
|
@@ -1,546 +0,0 @@
|
|
|
1
|
-
# 共享 VFX 特效库 — 综合方案 (v2)
|
|
2
|
-
|
|
3
|
-
> 本文把团队既有调研、两份 ChatGPT 设计稿(`VFX_LIBRARY_ARCHITECTURE_chatgpt.md`、`vfx-integration_chatgpt.md`)与平台负责人敲定的方向**综合成一份可执行方案**。
|
|
4
|
-
>
|
|
5
|
-
> **主线 = 已敲定的三个决策**,其余设计一律服从主线。
|
|
6
|
-
>
|
|
7
|
-
> **v1.1 修订**:对 v1 跑过一轮对抗式代码审查(对照 `lumber-order` / `pa_template` / 旧库真实代码),修正若干「与现状不符 / 落地会翻车」的点;关键纠正在 §4.2、§5、§6、§7、§9,新增 §4.5。
|
|
8
|
-
>
|
|
9
|
-
> **v2 修订(本版,重要)**:经两项目实跑验证 + 三个新的设计决策落定,§1–§15 的部分结论被 §16 起的新章节**收敛/修订**;**冲突时以 §16–§21 为准**。三个新决定:① 分发改走**依赖模型(C)**、复用 `@fps-games/editor` 发布蓝图(§18);② **库纯净契约**——库禁止引用项目、项目只做参数绑定(§17);③ alias 工具采用**克隆 editor `aliases.ts`**(§18.3)。§20 为修订版总计划与剩余任务,§21 为 pa_template 新项目验证计划。**当前实跑进度**:两项目已完成「机制」全量迁移(手动注册→glob),但 §16–§19 的「真共享包 + 纯净化 + 工具链」尚未落地——见 §20 勾选状态。
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## 0. 主线决策(不可动摇的前提)
|
|
14
|
-
|
|
15
|
-
| # | 决策 | 选择 | 含义 |
|
|
16
|
-
|---|------|------|------|
|
|
17
|
-
| 1 | **运行时格式** | **混合** | 标准粒子用数据(`effect.json` 的 `emitters[]`)+ 通用 data adapter 描述,AI/工具可生成;复杂/非标特效用 `index.ts` 手写 `create()` 逃生舱。两类对外接口统一。 |
|
|
18
|
-
| 2 | **调试主场** | **项目内 DEV 面板为主** | 沿用现有 `runtime-vfx-debug-panel` 模式,dev-server 存回 JSON。编辑器内 Inspector / 非技术用户线**推后**。 |
|
|
19
|
-
| 3 | **库实体与检索** | **先做纯 git/ESM 包** | monorepo + `index.json` + glob 自动发现;**暂不接 Supabase / Registry / CDN**,后续再说。 |
|
|
20
|
-
|
|
21
|
-
这三条共同决定第一版是一条**「把已跑通的能力沉淀成可复用库、最快落地、最低耦合」**的路线,而非一上来做 Package Manager / Marketplace。
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
## 1. 背景与目标
|
|
26
|
-
|
|
27
|
-
Playable 平台面向非技术用户与 Agent,特效高频出现。当前痛点(调研结论):
|
|
28
|
-
|
|
29
|
-
- **`lumber-order` / `lumber-truck` 已各自演化出同一套 `VfxEffectPackage` 体系**(`vfx-integration_chatgpt.md` 描述的就是它),**且已包含 data 特效的运行时 adapter `createManifestRuntimeEffectPackage`**;但靠**复制粘贴**流转、**手动注册**、调参只在 dev-server 落盘。
|
|
30
|
-
- **旧库 `fps-vfx-library` 擅长「产出 + 描述」**:Cocos→Babylon 转换、`effect.json`(emitters + tunableParams + 引擎注入式 ESM adapter)、`description.json`(AI 检索元数据)、预览媒体;但**没有顶层索引、绑 GCS、运行时在别的 repo,且其 adapter 与项目里那份已经分叉**(见 §4.5)。
|
|
31
|
-
- **新项目脚手架 `pa_template` 的 VFX 反而落后**:内置 `SceneVfxService` 只 117 行,只能配 position/rotation/textureId/capacity,粒子参数写死,**没有** `EffectPackageService` / `playEffectPackage` / 包系统。
|
|
32
|
-
|
|
33
|
-
> **目标:把特效像资产一样被浏览、安装、调试、复用。** 第一版只要跑通最小闭环:**选中特效 → 导入项目 → 自动出现在调试面板 → 调参 → 存回项目 → 构建只打包用到的特效。**
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
## 2. 与两份 ChatGPT 方案的取舍
|
|
38
|
-
|
|
39
|
-
两份稿子定位不同:`vfx-integration` 稿**忠实描述现状运行时**(本方案直接抽取);`ARCHITECTURE` 稿是**中长期愿景**(超出 MVP,裁剪后分阶段吸收)。取舍如下:
|
|
40
|
-
|
|
41
|
-
| 主题 | 两份稿的立场 | 本方案 | 理由(对齐主线) |
|
|
42
|
-
|------|-------------|--------|----------------|
|
|
43
|
-
| 中央库 vs 项目使用分离 | ARCH ✅ 强调 | **采纳** | 调参写项目、不污染库默认值,核心原则 |
|
|
44
|
-
| 特效是 Package 而非代码片段 | 两稿 ✅ | **采纳** | manifest + 默认参数 + 参数 schema + 预览 |
|
|
45
|
-
| schema 驱动的统一调试面板 | 两稿 ✅ | **采纳** | 正是现有 `debugParams` 驱动面板的做法 |
|
|
46
|
-
| 运行时格式 | **两稿都是 code 端**(手写 `create()`) | **加上 data 端做成混合** | 主线①:data 端来自**旧库 emitters + 现有 `createManifestRuntimeEffectPackage`**,不是某一稿提出的 |
|
|
47
|
-
| 调试主场 | ARCH=编辑器 Inspector;**integration=项目内 DEV 面板(现状)** | **采纳 integration 的项目内面板,推后 ARCH 的编辑器线** | 主线②:最快落地 |
|
|
48
|
-
| 库存放与检索 | ARCH=Registry/CDN/lock/动态下载 | **改为纯 git/ESM 包 + index.json + glob** | 主线③:暂不接平台资产系统 |
|
|
49
|
-
| 版本管理 | ARCH §22.5 **明确反对**复杂解析/自动升级,只建议「固定版本 + lock + 手动升级」 | **进一步简化**:manifest 带 `version`,靠 git;第一版连 lock 都不做 | 主线③:第一版不做包管理器 |
|
|
50
|
-
| Usage / Binding / EventBinding(数据化放置) | ARCH ✅ 一等概念 | **推后**(现用 gameplay System 代码触发) | 属编辑器授权线 |
|
|
51
|
-
| `vfxDependencies`(已安装清单) | ARCH ✅ 一等概念 | **被 §6「copy 目录 + glob 自动发现」取代**(项目里有哪些目录 = 安装了哪些) | 纯包模型下更干净;非静默丢弃 |
|
|
52
|
-
| 自动选中 + 自动开面板 | ARCH ✅(编辑器内) | **降级**:面板里导入即出现在下拉、可一键预览 | 编辑器自动选中属推后线 |
|
|
53
|
-
| 隔离预览 stage | ARCH ✅ | **推后**(MVP 用 in-game 预览 + debugAnchor) | 先复用现成能力 |
|
|
54
|
-
| 构建期 tree-shake、只打包用到的特效 | ARCH ✅ | **采纳**,但用「effects/(常驻)+ effects-debug/(仅 dev glob)」实现 | 见 §9 |
|
|
55
|
-
| Agent 工作流 | ARCH ✅ | **采纳** | §11 |
|
|
56
|
-
| **glob 自动发现(干掉手动注册)** | ❌ 两稿都没有 | **新增,头号收益** | 跨项目复用的最大障碍就是手改 `index.ts` |
|
|
57
|
-
| **混合契约 + 适配层** | ❌ 两稿各只覆盖一半 | **新增,技术核心** | §4 |
|
|
58
|
-
|
|
59
|
-
---
|
|
60
|
-
|
|
61
|
-
## 3. 核心概念(第一版保留 3 个,推后 1 类)
|
|
62
|
-
|
|
63
|
-
| 概念 | 说明 | 第一版 |
|
|
64
|
-
|------|------|--------|
|
|
65
|
-
| **VFX Package** | 中央库里的一个特效:`index.ts`(导出 `VfxEffectPackage`)+ 资源 + 参数定义 + 默认值 + 预览 + 版本 | ✅ |
|
|
66
|
-
| **Library Default** | 库里该特效的默认参数(`defaultParams`),概念上只读 | ✅ |
|
|
67
|
-
| **Project Saved Params** | 特效**被复制进项目后**的调参定稿(项目内 `vfx-params.json`),不回写库 | ✅ |
|
|
68
|
-
| **Preview Session** | 面板里正在临时调、尚未保存的值 | ✅ |
|
|
69
|
-
| ~~Usage / Binding / EventBinding~~ | 数据化描述「特效在场景哪里 / 哪个事件触发」 | **推后**(现用 System 代码触发) |
|
|
70
|
-
| ~~vfxDependencies~~ | 已安装清单 | **被 glob 取代**(目录在 = 已安装) |
|
|
71
|
-
|
|
72
|
-
> **不变量**(ARCH §15、§22.1):项目里的调参只写进**项目自己的** `vfx-params.json`,不回写库 `defaultParams`。澄清两种语境:**库内**运行面板 = 作者在生产/打磨该特效的 seed 参数(预期行为);**项目内**运行面板 = 改本项目的 ③ 层 saved。因为特效是被**复制**进项目的,两份天然分离,互不污染。
|
|
73
|
-
|
|
74
|
-
---
|
|
75
|
-
|
|
76
|
-
## 4. 技术核心:统一的混合 `VfxEffectPackage` 契约
|
|
77
|
-
|
|
78
|
-
主线①要求让「数据驱动」与「代码驱动」两类特效**对外长成同一个样子**。实现这点的关键约定是:
|
|
79
|
-
|
|
80
|
-
> **每个特效(无论 data 或 code)都出一个 `index.ts`,默认导出(或具名导出)一个 `VfxEffectPackage`。** code 特效手写 `create()`;data 特效的 `index.ts` 是一层薄包装,调用现有的 `createManifestRuntimeEffectPackage(effectJson, assetUrls)` 产出同样的 `VfxEffectPackage`。
|
|
81
|
-
|
|
82
|
-
这一条同时解决三件事:发现统一(只 glob `index.ts`)、区分免判别(都导出 package,`kind` 仅作信息字段)、资源 URL 由该 `index.ts` 用 Vite `?url` import 解析(见 §4.5)。
|
|
83
|
-
|
|
84
|
-
### 4.1 统一接口(在现有 `src/assets/vfx/types.ts` 基础上扩展)
|
|
85
|
-
|
|
86
|
-
```ts
|
|
87
|
-
export type VfxEffectKind = 'data' | 'code';
|
|
88
|
-
|
|
89
|
-
export interface VfxEffectPackage<P extends VfxParamValues = VfxParamValues> {
|
|
90
|
-
id: string; // 全局唯一 = 目录名
|
|
91
|
-
nameZh: string;
|
|
92
|
-
// —— 以下为本方案新增(types.ts 现状没有)——
|
|
93
|
-
kind?: VfxEffectKind; // 'data' | 'code';信息字段,默认按是否走 data adapter 推断
|
|
94
|
-
version?: string; // 第一版仅记录,不做 lock
|
|
95
|
-
nameEn?: string;
|
|
96
|
-
debugOnly?: boolean; // 仅调试用、不进 prod 包(替代显式 DEBUG 数组,见 §9)
|
|
97
|
-
// —— 以下为 types.ts 现状字段(保持)——
|
|
98
|
-
manifest?: VfxEffectManifest; // 现状仅 { id, nameZh, assets?, source? };富目录字段不在这里(见下)
|
|
99
|
-
defaultParams: P; // Library Default(全量兜底)
|
|
100
|
-
savedParams?: Partial<VfxParamValues>; // Project Saved(项目内 vfx-params.json,注册时回填)
|
|
101
|
-
debugParams: VfxParamDefinition[];// 面板控件定义数组(= 旧库 tunableParams 的上位)
|
|
102
|
-
debugAnchor?: VfxDebugAnchor; // 预览锚点;锚点名由**宿主项目**解析(库不应硬编码游戏锚点)
|
|
103
|
-
spawnParams?: VfxSpawnParamKeys;
|
|
104
|
-
create(ctx: VfxEffectPackageContext<P>): VfxEffectHandle;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export interface VfxEffectPackageContext<P> {
|
|
108
|
-
scene: Scene;
|
|
109
|
-
root: TransformNode; // 服务层已建好(位置/朝向已设置)
|
|
110
|
-
position: Vector3;
|
|
111
|
-
rotationY: number;
|
|
112
|
-
renderingGroupId?: number;
|
|
113
|
-
params: P;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export interface VfxEffectHandle {
|
|
117
|
-
root: TransformNode; // code 类可 reparent 跟随;data 类详见 §4.5
|
|
118
|
-
ready?: Promise<void>; // ★ 现状字段:warmup/异步资源就绪用,勿漏
|
|
119
|
-
dispose(): void;
|
|
120
|
-
}
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
参数值仍收窄为三种,保证可 JSON 落盘、可被面板编辑:
|
|
124
|
-
|
|
125
|
-
```ts
|
|
126
|
-
export type VfxColorValue = { r: number; g: number; b: number };
|
|
127
|
-
export type VfxParamValue = number | string | VfxColorValue;
|
|
128
|
-
export type VfxParamValues = Record<string, VfxParamValue>;
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
> **纠正 v1 的两个高估**:(a) `manifest` 现状是**可选**且只含 `{id, nameZh, assets?, source?}`,**不含** category/tags/preview/capabilities/performance——这些富检索字段只存在于旧库 `effect.json` 的 `search`/`recording` 和 `description.json`;本方案把它们归到 `description.json` 与 `index.json`(§5),**不塞进运行时 manifest**。(b) `VfxEffectHandle` 现状有 `ready?`,抽库时必须保留。
|
|
132
|
-
|
|
133
|
-
### 4.2 两条路径如何统一
|
|
134
|
-
|
|
135
|
-
- **`kind: 'code'`(逃生舱,现状写法,无需改动)**:`index.ts` 手写 `create()`(如 `vehicle-exhaust-smoke`:SpriteManager + 精灵池 + `onBeforeRenderObservable` 自驱动 + 确定性随机)。表现力最强,且**只有它能用 `root.getWorldMatrix()` 真正跟随宿主**。
|
|
136
|
-
|
|
137
|
-
- **`kind: 'data'`(可生成)**:`index.ts` 是薄包装。data 端的运行时**已经存在**——`lumber-order` 的 `createManifestRuntimeEffectPackage`(`src/assets/vfx/manifestRuntimePackage.ts`):读 `effect.json` 的 `emitters[]` + `tunableParams[]`,逐 emitter 调引擎注入式 adapter(`particleEmitter/v1`、`simpleMeshEffect/v1`),合成标准 `VfxEffectPackage` 并返回 `{ root, ready, dispose }`;`defaultParams` 由 `tunableParams[].default` 派生。**本方案是把它沉淀进 `@fps/vfx-runtime`,不是新写。** 一个 data 特效的 `index.ts` 形如:
|
|
138
|
-
|
|
139
|
-
```ts
|
|
140
|
-
// effects/build.particle.wood_chip_dust_burst/index.ts(data 包薄包装)
|
|
141
|
-
import effectJson from './effect.json';
|
|
142
|
-
import suipian3Url from './assets/textures/suipian3.png?url';
|
|
143
|
-
import yanwuUrl from './assets/textures/effect_yanwu4.png?url';
|
|
144
|
-
import { createDataDrivenEffectPackage } from '@fps/vfx-runtime';
|
|
145
|
-
|
|
146
|
-
export default createDataDrivenEffectPackage(effectJson, {
|
|
147
|
-
// packagePath → 打包后可用 URL 的映射(供 urlForPackagePath 用)
|
|
148
|
-
'assets/textures/suipian3.png': suipian3Url,
|
|
149
|
-
'assets/textures/effect_yanwu4.png': yanwuUrl,
|
|
150
|
-
});
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
**统一点**:registry 拿到的都是 `{ id, nameZh, kind, defaultParams, debugParams, create()→{root,ready?,dispose} }`;**面板只认 `debugParams`,与 `kind` 无关**;`SceneVfxService` 只调 `create()`。
|
|
154
|
-
|
|
155
|
-
### 4.3 参数键 / 颜色 / 落盘格式约定(必须现在统一)
|
|
156
|
-
|
|
157
|
-
现有两个项目并存两套写法,必须收敛(否则面板与合并逻辑会乱):
|
|
158
|
-
|
|
159
|
-
- **键名**:`kind:'data'` 用 `<emitter>.<property>` 命名空间键(对齐旧库 `tunableParams.target` 与 `tree_chop_dust_burst` 写法);`kind:'code'` 用作者在 `debugParams` 里定义的扁平键。
|
|
160
|
-
- **颜色**:内存一律 `VfxColorValue {r,g,b}`;JSON 里 `{r,g,b}` 与 `#rrggbb` hex **都接受**,由 `sanitizeParamsFile()` 归一(现状 adapter 已做 hex→{r,g,b},见 `manifestRuntimePackage`)。
|
|
161
|
-
- **落盘文件**:`schemaVersion` 现状是 **string**(如 `'vfx-params/1.0'`),不是数字。统一成带壳格式,并兼容现存的裸扁平文件:
|
|
162
|
-
|
|
163
|
-
```jsonc
|
|
164
|
-
// 项目内 effects/<id>/vfx-params.json
|
|
165
|
-
{
|
|
166
|
-
"schemaVersion": "vfx-params/1.0",
|
|
167
|
-
"effectId": "build.particle.wood_chip_dust_burst",
|
|
168
|
-
"updatedAt": "2026-06-26T00:00:00.000Z",
|
|
169
|
-
"params": { "shumu.minSize": 0.5, "shumu.renderColor.color": "#ffffff" }
|
|
170
|
-
}
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
`sanitizeParamsFile()` 同时接受裸 `{ ...params }`(现存 `tree_chop_dust_burst/vfx-params.json` 即裸扁平)和带壳 `{ params }`,向后兼容。
|
|
174
|
-
|
|
175
|
-
> **`id` 命名**:`id = 目录名`,全局唯一。现存两种风格并存——旧库点分 `category.type.name`、项目里 kebab/snake(`vehicle-exhaust-smoke`)。**不强制改名**(旧库 lineage 已证明 id 漂移是真问题);新建特效推荐点分 `category.type.name`。`validate-manifest` 负责跨包唯一性校验。
|
|
176
|
-
|
|
177
|
-
### 4.4 调参 = 重建预览(第一版不强制 `updateParams`)
|
|
178
|
-
|
|
179
|
-
参考 ARCH §8(原文 50–100ms),现状面板做法:
|
|
180
|
-
|
|
181
|
-
```text
|
|
182
|
-
参数变化 → debounce ~90–180ms → dispose 当前预览 → 用新参数重新 create
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
好处:所有特效都支持、Runtime 接口简单、结果确定、易做自动截图回归。
|
|
186
|
-
|
|
187
|
-
### 4.5 适配层与已知限制(★ v1.1 新增,落地前必读)
|
|
188
|
-
|
|
189
|
-
「复制旧库目录即用」对 data 包**不成立**,因为旧库 adapter 与项目里那份已分叉。沉淀进 `@fps/vfx-runtime` 时必须吸收 `lumber-order` 已经打过的补丁,并明确当前能力边界:
|
|
190
|
-
|
|
191
|
-
1. **定位**:旧库 `particleEmitter.v1.js` 把 `system.emitter = Vector3.Zero()`(粒子固定世界原点),**不建 root、不读外部位置**。`lumber-order` 版已改为读 `emitter.origin`,由 `createManifestRuntimeEffectPackage` 从 `context.position` 注入。→ 沉淀时以 lumber-order 的**已打补丁 adapter** 为准;旧库 6 个包迁移时需替换其 `assets/runtime/*.js`。
|
|
192
|
-
2. **跟随**:粒子/mesh adapter **不导出 `setPosition`**,故 **data 类只能一次性定位、不跟随宿主移动**;需要跟随的特效用 **code 类**(`root.getWorldMatrix()`)。§7 据此修正。
|
|
193
|
-
3. **mesh 特效**:`simpleMeshEffect.v1.js` 用 `fetch()` 拉 `.glsl` 注入 `Effect.ShadersStore`,且自建内部 root、按 `meshEffect.offset` 定位(不读 origin)。→ 着色器必须以 `?url` 打进 bundle(不能只靠 ESM 字符串 import)。
|
|
194
|
-
4. **贴图/资源 URL**:adapter 用 `urlForPackagePath(packagePath)` 解析;旧库 `effect.json` 里纹理是 `packagePath`(相对)+ `sourcePath: gs://...`。→ 每个 data 包的 `index.ts` 必须用 `?url` import 把每个 `packagePath` 映射成打包 URL(见 §4.2 示例),否则回退成裸路径 404。
|
|
195
|
-
5. **运行时 js**:`particleEmitter.v1.js` 等作为引擎注入式 adapter 由核心统一持有(沉淀进 `@fps/vfx-runtime/adapters`),**不再每包夹带一份**;包里只留数据与资源。
|
|
196
|
-
|
|
197
|
-
---
|
|
198
|
-
|
|
199
|
-
## 5. 库的结构(纯 git/ESM monorepo)
|
|
200
|
-
|
|
201
|
-
`fps-vfx-library` 升级成 pnpm workspace,三类产物分离(ARCH §6.3 职责边界):
|
|
202
|
-
|
|
203
|
-
```text
|
|
204
|
-
fps-vfx-library/
|
|
205
|
-
├── packages/
|
|
206
|
-
│ ├── runtime/ # @fps/vfx-runtime —— 共享运行时核心(ESM 包)
|
|
207
|
-
│ │ ├── types.ts # VfxEffectPackage / Context / Handle(含 ready?)/ ParamDefinition
|
|
208
|
-
│ │ ├── EffectPackageService.ts # 注册 / 查包 / 五层参数合并 / 追踪 / 销毁
|
|
209
|
-
│ │ ├── SceneVfxService.ts # 门面:playEffectPackage / initFromConfig / warmup / dispose
|
|
210
|
-
│ │ ├── dataEffect.ts # createDataDrivenEffectPackage(= 沉淀 manifestRuntimePackage)
|
|
211
|
-
│ │ ├── adapters/ # particleEmitter/v1、simpleMeshEffect/v1(已打补丁版,统一持有)
|
|
212
|
-
│ │ ├── rendering.ts # VFX_RENDERING_GROUP_ID=2 / configureVfx*
|
|
213
|
-
│ │ ├── debug-panel.ts # 通用 DEV 调试面板(debugParams 驱动)
|
|
214
|
-
│ │ └── buildRegistry.ts # 把 glob 结果合成 registry(glob 调用本身在项目侧,见 §6.3)
|
|
215
|
-
│ └── effects/ # 每个特效一个包
|
|
216
|
-
│ └── <category.type.name>/ # 如 build.particle.wood_chip_dust_burst
|
|
217
|
-
│ ├── index.ts # ★ 必有:导出 VfxEffectPackage(code 手写 / data 薄包装)
|
|
218
|
-
│ ├── effect.json # data:manifest + emitters[];code:manifest
|
|
219
|
-
│ ├── vfx-params.json # 库 seed 参数(被复制进项目后由项目覆盖)
|
|
220
|
-
│ ├── assets/ # 贴图 / 着色器
|
|
221
|
-
│ ├── media/ # thumbnail / preview.mp4|webm|gif / contact-sheet
|
|
222
|
-
│ └── description.json # AI 检索元数据(vfx-description/1.1):tags/usageScenarios/关键词
|
|
223
|
-
├── index.json # 顶层目录(generate-index 生成):列出全部特效
|
|
224
|
-
├── tooling/
|
|
225
|
-
│ ├── generate-index.ts # 扫 packages/effects 生成 index.json
|
|
226
|
-
│ ├── validate-manifest.ts # 校验 effect.json / debugParams / 资源完整 / id 跨包唯一
|
|
227
|
-
│ └── vfx-add.ts # CLI:把某特效复制进目标项目
|
|
228
|
-
└── docs/
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
`index.json`(ARCH §20.1 的 `registry.json`,纯本地静态版)。其 `category`/`tags`/`media` **取自 `description.json`**(单一来源,避免与 manifest 双源不一致):
|
|
232
|
-
|
|
233
|
-
```jsonc
|
|
234
|
-
{
|
|
235
|
-
"schemaVersion": "vfx-index/1.0",
|
|
236
|
-
"effects": [{
|
|
237
|
-
"id": "build.particle.wood_chip_dust_burst",
|
|
238
|
-
"kind": "data", "version": "1.0.0", "debugOnly": false,
|
|
239
|
-
"nameZh": "木屑烟尘爆发",
|
|
240
|
-
"category": "build", "tags": ["wood","dust","burst"], // 来自 description.json
|
|
241
|
-
"media": { "thumbnail": "...", "preview": "..." },
|
|
242
|
-
"path": "packages/effects/build.particle.wood_chip_dust_burst"
|
|
243
|
-
}]
|
|
244
|
-
}
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
> **向后兼容**:旧库现有 6 个包是 data 类(emitters + tunableParams)。迁移 = 为每个包加 `index.ts` 薄包装 + `?url` 资产映射、把 `tunableParams` 映射成 `debugParams`、替换其运行时 js 为已打补丁版(§4.5)、补 `kind/version`、生成 `index.json`。**不重做 Cocos→Babylon 转换管线。**
|
|
248
|
-
|
|
249
|
-
---
|
|
250
|
-
|
|
251
|
-
## 6. 怎么「选中」+「导入」项目(无 Registry / CDN)
|
|
252
|
-
|
|
253
|
-
### 6.1 选中
|
|
254
|
-
|
|
255
|
-
- **开发者 / Agent**:读 `index.json` 或各包 `description.json` 检索(语义标签 / usageScenarios / 关键词;预览看 `media/`)。
|
|
256
|
-
- (推后)接平台 Supabase 目录与 `fps-game-editor` asset browser 后,人看缩略图网格、Agent 走 hybrid search。
|
|
257
|
-
|
|
258
|
-
### 6.2 导入 = CLI 复制 + glob 自动注册
|
|
259
|
-
|
|
260
|
-
```bash
|
|
261
|
-
npx vfx add build.particle.wood_chip_dust_burst # 在项目根执行
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
`vfx add` 做的事:
|
|
265
|
-
1. 从库 `packages/effects/<id>/` 复制到项目 `src/assets/vfx/effects/<id>/`(含 index.ts / effect.json / vfx-params.json / assets / media)。
|
|
266
|
-
2. 校验项目已装 `@fps/vfx-runtime`(没有则提示)。
|
|
267
|
-
3. **覆盖策略**:默认**跳过已存在**的特效并提示;`--force` 才覆盖;**绝不**在无 `--force` 时 clobber 项目里已被本地改动的 `vfx-params.json`(按内容/时间戳判断,改动过则单独警告)。
|
|
268
|
-
4. 完。**不需要手改任何 `index.ts` 注册**——项目侧靠 glob 自动发现。
|
|
269
|
-
|
|
270
|
-
### 6.3 glob 自动发现(头号收益)
|
|
271
|
-
|
|
272
|
-
把现状那段「手写 import + 三处登记」(`vfx-integration` §3.2)替换成 glob。**注意 `import.meta.glob` 必须写在项目代码里**(Vite 编译期按所在文件相对解析;写进 `@fps/vfx-runtime` 会相对 `node_modules/` 解析、扫不到项目特效)。`buildRegistry` 这个纯函数可放库里:
|
|
273
|
-
|
|
274
|
-
```ts
|
|
275
|
-
// 项目 src/assets/vfx/index.ts(glob 在此;buildRegistry 来自库)
|
|
276
|
-
import { buildRegistry } from '@fps/vfx-runtime';
|
|
277
|
-
|
|
278
|
-
// 每个特效目录都有 index.ts(code 手写 / data 薄包装),统一发现:
|
|
279
|
-
const modules = import.meta.glob('./effects/*/index.ts', { eager: true });
|
|
280
|
-
const params = import.meta.glob('./effects/*/vfx-params.json', { eager: true });
|
|
281
|
-
// 仅 dev 才扫调试专用特效(prod 构建里这行被 import.meta.env.DEV 短路,见 §9):
|
|
282
|
-
const debugModules = import.meta.env.DEV
|
|
283
|
-
? import.meta.glob('./effects-debug/*/index.ts', { eager: true }) : {};
|
|
284
|
-
|
|
285
|
-
export const { VFX_EFFECT_PACKAGES, VFX_EFFECT_PACKAGE_MAP } =
|
|
286
|
-
buildRegistry({ modules, debugModules, params });
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
`buildRegistry` 的明确契约:
|
|
290
|
-
- 从 glob 的 path key 取出 `<id>` 段(= 目录名);
|
|
291
|
-
- 每个 `index.ts` 模块取其导出的 `VfxEffectPackage`(优先 `default`,否则取第一个形如 package 的具名导出——名字逐特效不同,不能按固定 key 取);
|
|
292
|
-
- `.json` 模块取 `.default`(eager 下 JSON 是 `{ default: 解析对象 }`),经 `sanitizeParamsFile` 注入对应包的 `savedParams`;
|
|
293
|
-
- **id 冲突**:同 id 出现两次 → 抛错(开发期立刻暴露),并提示来源目录。
|
|
294
|
-
|
|
295
|
-
> 这样「导入特效」= 丢一个目录进 `effects/`,**自动出现在 registry 与面板下拉**。因为 code/data 都经各自 `index.ts` 导出 package,**发现端无需判别 kind、无需依赖 manifest 文件名**——解决了 v1 里 buildRegistry 区分 code/data 的漏洞。
|
|
296
|
-
|
|
297
|
-
---
|
|
298
|
-
|
|
299
|
-
## 7. 运行时:加载 / 播放 / 销毁(沿用现状,下沉到库)
|
|
300
|
-
|
|
301
|
-
完全采纳 `vfx-integration` 描述的现有运行时(已验证),抽进 `@fps/vfx-runtime`:
|
|
302
|
-
|
|
303
|
-
- **入口**:`SceneVfxService.playEffectPackage(effectId, explicitParams?, spawnTransform?) → VfxEffectHandle | null`。
|
|
304
|
-
- **五步**(`EffectPackageService`):查包(查不到 `console.warn` 返回 null)→ 合并参数 → 建 `root` 应用位置/朝向/生成偏移 → 调 `package.create(ctx)` → 追踪 handle 并包装 dispose(自动从 `activeHandles` 移除)。
|
|
305
|
-
- **参数合并(五层,后者覆盖前者)** —— 与真实 `getMergedParams` 逐项吻合:
|
|
306
|
-
|
|
307
|
-
```text
|
|
308
|
-
① VFX_DEFAULT_GENERATION_PARAMS 生成偏移(__generation.offsetX/Y/Z,默认 0)
|
|
309
|
-
② package.defaultParams Library Default(全量兜底)
|
|
310
|
-
③ package.savedParams Project Saved(项目 vfx-params.json;= 愿景 Project Preset)
|
|
311
|
-
④ service.savedParams[id] 运行时/预览面板覆盖(setDebugOverride 写入的内存层)
|
|
312
|
-
⑤ explicitParams gameplay 调用传入(最高优先级)
|
|
313
|
-
```
|
|
314
|
-
> ARCH §15 把 Preview Session 排在**最顶**;现状实现里 explicitParams 最高(⑤)。本方案**以已验证的现状为准**,不照搬 §15 的层序。愿景的 Published Preset / Usage Override 先并入 ③,将来上编辑器/Usage 线时再拆层。
|
|
315
|
-
|
|
316
|
-
- **跟随**:**仅 code 类**可 reparent(`handle.root.parent = node; root.position = localOffset`),方向用 `root.getWorldMatrix()` 变换,对宿主零感知;**data 类一次性定位、不跟随**(§4.5)。
|
|
317
|
-
- **三条销毁路径**:手动 `handle.dispose()` / 超时 setTimeout / `Game.dispose() → SceneVfxService.dispose()` 遍历 `activeHandles` 兜底。重复 dispose 安全(内部 `disposed` 标志)。
|
|
318
|
-
- **统一渲染**:`VFX_RENDERING_GROUP_ID = 2`,创建后必调 `configureVfxParticleSystem/SpriteManager`。
|
|
319
|
-
- **常驻环境粒子**:保留 `initFromConfig()`(读 `scene.json` 的 `tuning.sceneVfx`,走写死参数的旧粒子路径),与特效包系统并行。
|
|
320
|
-
- **错误兜底(MVP 必做)**:malformed `effect.json`、缺失贴图、`createDataDrivenEffectPackage`/`create` 抛错,运行期需 try/catch 降级为 warn + 跳过该特效,不可让单个坏包崩掉整个场景。
|
|
321
|
-
|
|
322
|
-
---
|
|
323
|
-
|
|
324
|
-
## 8. 调试面板(主线②:项目内 DEV 面板为主)
|
|
325
|
-
|
|
326
|
-
把现有面板(`runtime-vfx-debug-panel.ts`)抽进 `@fps/vfx-runtime`,在 `pa_template` 用其**已有通用面板框架**挂载:
|
|
327
|
-
|
|
328
|
-
- **挂载**:`pa_template` 的 `src/debug/framework/panel-layout.ts`(`mountRuntimeDebugPanel` + `installDebugPanelLayout`)+ 在 `src/debug/panel-manifest.ts`(现为空占位数组)注册一个 VFX descriptor。**DEV-only,prod 剥离**。
|
|
329
|
-
- **能力**(现状已有,保留):特效下拉(registry 的 `id`/`nameZh` 填充,新导入的自动出现)、按 `debugParams` 自动生成控件(number/color/enum/opacity/lifetime/scale)、生成参数与特效参数分区、播放/重置/保存、debounce 重建式实时预览、草稿存 localStorage、in-game 预览(`debugAnchor` 在真实场景播放 = ARCH §14.2)。
|
|
330
|
-
- **存盘**:沿用现有 Vite 中间件 `/__debug_panel_config`(面板实请求 `?file=effects/<id>/vfx-params.json`,POST `replace` 整文件写),**写回项目内该特效的 `vfx-params.json`**(随代码提交)。注意现状还存在第二个写同文件的端点 `/__vfx_debug_overrides`(壳为 `vfx-params/1.0`);库化时**统一成一个口径**。
|
|
331
|
-
- **Agent 友好**:保留 `window.__paDebugActionRegistry`(headless 调用)。
|
|
332
|
-
|
|
333
|
-
> 推后:编辑器内 VFX Inspector(`fps-game-editor` asset browser 加 `vfx` tab + Inspector v2 调参 + 自动选中)、隔离预览 stage。设计上**保留接口**:`debugParams` 与 `description.json` 是一等数据,将来直接喂编辑器/Supabase,无需重做。
|
|
334
|
-
|
|
335
|
-
---
|
|
336
|
-
|
|
337
|
-
## 9. 构建与打包(轻量 tree-shake)
|
|
338
|
-
|
|
339
|
-
采纳 ARCH §18 目标,但要与现状的体积控制机制兼容:
|
|
340
|
-
|
|
341
|
-
- 现状用显式数组 `PRODUCTION_VFX_EFFECT_PACKAGES` / `DEBUG_VFX_EFFECT_PACKAGES` + 生产期别名 `index.production.ts`(`vite.config.ts`)剥离调试特效。**纯 glob 会把 `effects/` 下所有特效 eager 打进包**,无法靠运行时 flag 减小体积。
|
|
342
|
-
- **解决**:目录分流——常驻特效放 `effects/`,**仅调试用**特效放 `effects-debug/`;`effects-debug/*` 的 glob 用 `import.meta.env.DEV` 短路(§6.3),prod 构建里整段被 tree-shake 掉。包对象的 `debugOnly` 字段用于面板归类与校验。
|
|
343
|
-
- 复制进项目的特效天然只含用到的;最终包不含远程依赖、不打整库、可复现。
|
|
344
|
-
- (推后)真正的 dependency-lock / 远程 bundle 收集,等接 Registry 时再做。
|
|
345
|
-
|
|
346
|
-
---
|
|
347
|
-
|
|
348
|
-
## 10. `pa_template` 集成(绕不开的统一动作)
|
|
349
|
-
|
|
350
|
-
**模板落后于项目**,顺序必须是「先把成熟核心 backport 进模板,再抽库」:
|
|
351
|
-
|
|
352
|
-
1. 用 `@fps/vfx-runtime`(从 lumber-order/truck 抽出)**替换** `pa_template` 现在那个 117 行弱版 `SceneVfxService`,保留 `Game` 期望的生命周期钩子(`new SceneVfxService(scene)` / `initFromConfig()` / `dispose()`)。
|
|
353
|
-
2. 项目侧 `src/assets/vfx/index.ts` 改成 §6.3 glob 自动发现。
|
|
354
|
-
3. 在 `panel-manifest.ts` 注册通用 VFX 面板;dev-server 加 `/__debug_panel_config` 中间件(从 lumber-order 移植)。
|
|
355
|
-
4. **验收**:丢一个 data 包 + 一个 code 包进 `effects/` → 两者都在面板下拉出现 → 都能播放、调参、存回各自 `vfx-params.json`。
|
|
356
|
-
|
|
357
|
-
---
|
|
358
|
-
|
|
359
|
-
## 11. Agent 工作流(采纳 ARCH §19)
|
|
360
|
-
|
|
361
|
-
1. 读库 `index.json` → 知道有哪些特效。
|
|
362
|
-
2. 读 `effect.json` / `description.json` → 知道参数、能力、适用场景。
|
|
363
|
-
3. 读项目 `effects/` 目录(= 已安装)→ 知道项目有哪些特效。
|
|
364
|
-
4. 改视觉:优先改项目 `vfx-params.json`(③ 层),**不改库 `defaultParams`**。
|
|
365
|
-
5. 新增特效:补齐 `index.ts` / manifest / `debugParams` / 默认值 / 预览;data 类可直接生成 `emitters[]` + 薄包装,code 类写 `create()`。
|
|
366
|
-
6. 改完用面板预览或自动截图验证。
|
|
367
|
-
|
|
368
|
-
---
|
|
369
|
-
|
|
370
|
-
## 12. 分阶段计划(对齐主线 MVP,每阶段附可验收判据)
|
|
371
|
-
|
|
372
|
-
| 阶段 | 目标 | 关键任务 | 验收判据 |
|
|
373
|
-
|------|------|----------|----------|
|
|
374
|
-
| **P1 契约 + 核心抽取** | 定 v1 契约,核心成库 | 定 `VfxEffectPackage`(§4,补 kind/version/ready?);从 lumber-order 抽 `@fps/vfx-runtime`(types/Service/`dataEffect`/`adapters` 已打补丁版/rendering/panel/`buildRegistry`)。**glob 留在项目侧** | 用一个最小宿主**注册并播放「1 个 data 包 + 1 个 code 包」**,各自能调一个参数并生效 |
|
|
375
|
-
| **P2 模板集成** | 模板用上核心 | backport 进 `pa_template`(§10) | 丢一个 data + 一个 code 目录进去 → 面板出现、可调、存回 vfx-params.json(§10 验收) |
|
|
376
|
-
| **P3 迁移旧库 + 索引** | 旧库进统一格式 | 6 个包加 `index.ts` 薄包装 + `?url` 资产映射 + 替换已打补丁运行时 js;`tunableParams→debugParams`;`generate-index` 出 `index.json`;`validate-manifest`(含 id 唯一) | `index.json` 列全 6 包;每包能在 P1 宿主里定位正确(不落世界原点)并播放;validate 通过 |
|
|
377
|
-
| **P4 导入 CLI** | 一键导入 | `vfx add <id>` 复制 + 覆盖策略(§6.2)+ 安装校验 | 在干净项目 `vfx add` 一个包后 `pnpm dev` 即见效,重复 add 按策略跳过/警告 |
|
|
378
|
-
| **P5 打磨** | 稳健 | data adapter 覆盖更多 emitter/mesh 形态;`effects-debug/` 分流;运行期错误兜底;自动截图回归 | prod 构建不含 `effects-debug/*`;坏包不崩场景;关键特效截图回归通过 |
|
|
379
|
-
| **(推后) P6+** | 平台化 | 接 Supabase 目录 + 编辑器 asset browser/Inspector;Usage/Binding/EventBinding;Registry/CDN/lock;隔离预览 stage;Marketplace | —— |
|
|
380
|
-
|
|
381
|
-
**第一版闭环**:`选中(index.json/检索) → vfx add 导入 → glob 自动出现在面板 → 调参 → 存回 vfx-params.json → 构建只打包用到的特效`。
|
|
382
|
-
|
|
383
|
-
---
|
|
384
|
-
|
|
385
|
-
## 13. 必须现在拍掉的小决定
|
|
386
|
-
|
|
387
|
-
1. **参数键/颜色/落盘格式统一**(§4.3):data 用 `<emitter>.<property>`,code 用扁平键;颜色内存 `{r,g,b}`、JSON 双接受;落盘带壳 `schemaVersion:'vfx-params/1.0'` + `sanitizeParamsFile` 兼容裸文件。
|
|
388
|
-
2. **「每个特效都出 `index.ts`」+ glob 在项目侧**(§4、§6.3):这是去掉手动注册、统一 code/data 发现、解决资源 URL 的总钥匙,P1 就要定死。
|
|
389
|
-
3. **沉淀已打补丁的 adapter,不用旧库原版**(§4.5):否则旧库 data 包落世界原点 / 贴图 404。
|
|
390
|
-
4. **`debugParams` 与 `description.json` 当一等公民**:即便编辑器线推后,也按「将来直接喂编辑器/Supabase」标准设计。
|
|
391
|
-
|
|
392
|
-
---
|
|
393
|
-
|
|
394
|
-
## 14. 平台化自检清单(取自 ARCH §24,按本方案裁剪)
|
|
395
|
-
|
|
396
|
-
- [ ] 有唯一 `id`(=目录名)与 `version`、有 `index.ts` 导出 package、有默认参数、有 `debugParams`、有预览。
|
|
397
|
-
- [ ] 能被 `index.json` 发现、能被 `vfx add` 导入、能被 glob 自动注册(无需手改注册表)。
|
|
398
|
-
- [ ] 能被 `@fps/vfx-runtime` 加载、经 `SceneVfxService` 播放;data 类定位正确(经 `emitter.origin`),需跟随的用 code 类。
|
|
399
|
-
- [ ] 能在项目内 DEV 面板按 `debugParams` 调参;调参**只写项目 `vfx-params.json`,不污染库默认值**。
|
|
400
|
-
- [ ] 构建时只打包项目实际使用的特效;`effects-debug/*` 不进 prod。
|
|
401
|
-
- [ ] 三条销毁路径齐全、坏包有兜底;`data`/`code` 两类对外契约一致(含 `ready?`)。
|
|
402
|
-
- [ ] Agent 能通过 `debugParams` 与 `description.json` 理解并使用它。
|
|
403
|
-
|
|
404
|
-
---
|
|
405
|
-
|
|
406
|
-
## 15. 名词表(简表)
|
|
407
|
-
|
|
408
|
-
| 名词 | 含义 |
|
|
409
|
-
|------|------|
|
|
410
|
-
| VFX Package | 一个可复用特效:`index.ts` 导出 `VfxEffectPackage` + 资源 + 参数 schema + 默认值 + 预览 |
|
|
411
|
-
| `kind` | `data`(effect.json emitters + 通用 adapter)或 `code`(手写 create()) |
|
|
412
|
-
| `@fps/vfx-runtime` | 共享运行时核心:Service + `dataEffect` + `adapters` + rendering + 通用面板 + `buildRegistry` |
|
|
413
|
-
| `createDataDrivenEffectPackage` | data 包薄包装用的工厂(= 沉淀现有 `createManifestRuntimeEffectPackage`) |
|
|
414
|
-
| `index.json` | 库顶层静态目录(纯本地 registry),富字段取自 description.json |
|
|
415
|
-
| Library Default | 库里特效默认参数(`defaultParams`),概念只读 |
|
|
416
|
-
| Project Saved | 特效复制进项目后的调参定稿(项目内 `vfx-params.json`) |
|
|
417
|
-
| `debugParams` | 驱动调试面板自动生成控件的参数定义数组 |
|
|
418
|
-
| `SceneVfxService` / `EffectPackageService` | 播放/生命周期 与 注册/合并/查询 |
|
|
419
|
-
| `vfx add` | 把某特效从库复制进项目的 CLI |
|
|
420
|
-
|
|
421
|
-
---
|
|
422
|
-
|
|
423
|
-
*本方案以「主线三决策 + 综合两份 ChatGPT 稿」为基础,并经一轮对照真实代码的对抗式审查修订(v1.1)。`vfx-integration_chatgpt.md` 对应现状运行时(直接抽取),`VFX_LIBRARY_ARCHITECTURE_chatgpt.md` 对应中长期愿景(裁剪后分阶段吸收)。*
|
|
424
|
-
|
|
425
|
-
---
|
|
426
|
-
---
|
|
427
|
-
|
|
428
|
-
# v2 增补(以下章节为最新决策,冲突时优先于 §1–§15)
|
|
429
|
-
|
|
430
|
-
## 16. 分发与升级模型(从「拷贝」改为「依赖」)
|
|
431
|
-
|
|
432
|
-
v1 的 decision #3(纯 git 包 + `vfx add` 拷贝)有个根本代价:**拷贝 = vendoring = 会漂移、升级靠 sync**。这个问题**已经真实发生**——lumber-order 与 lumber-truck 的 23 个特效里 20 个实现已不一致。
|
|
433
|
-
|
|
434
|
-
### 两类内容,owner 不同(升级只能动其一)
|
|
435
|
-
| 内容 | owner | 升级时 |
|
|
436
|
-
|---|---|---|
|
|
437
|
-
| 代码 + 共享资源(index.ts / runtime js / shader / 基础贴图 / GLB) | **库(上游)** | 可被覆盖更新 |
|
|
438
|
-
| 调参 `vfx-params.json`(项目美术定稿,参数合并③层) | **项目** | **绝不能被覆盖** |
|
|
439
|
-
|
|
440
|
-
### 三模型
|
|
441
|
-
| 模型 | 升级 | 优点 | 代价 |
|
|
442
|
-
|---|---|---|---|
|
|
443
|
-
| A 拷贝(v1) | `vfx update`:重拷代码资源、留 params | 零耦合、离线、Playable 自包含可打包 | 会漂移;"一处修复全局升级"做不到 |
|
|
444
|
-
| B 依赖(npm/ESM) | 改版本号 + `pnpm i` | 代码真单一源、一处修复全生效 | 需 babylon peer/dedupe + `?url` from node_modules + glob 扫不到 node_modules |
|
|
445
|
-
| **C 混合(选定)** | 改版本号 | 代码/资源单一源 + 参数项目自治 + **glob 仍能扫到** + 升级=版本号 | 需 B 的机制(已由 editor 蓝图解决,见 §18) |
|
|
446
|
-
|
|
447
|
-
### 选定 = C(混合)
|
|
448
|
-
- 代码/资源在依赖包 `@fps/vfx`;项目里每个特效只留:**2 行 re-export 桩** `effects/<id>/index.ts`(`export { default } from '@fps/vfx/effects/<id>'`)+ 本地 `vfx-params.json`。
|
|
449
|
-
- glob 扫到桩 → 自动发现照旧;代码/资源在包里 → 单一源;升级 = bump 版本号。
|
|
450
|
-
- B 模型那些"坑"(babylon 多实例、`?url`、双模式 dev/versioned)**已被 `@fps-games/editor` 解决**,照搬即可(§18)。
|
|
451
|
-
|
|
452
|
-
## 17. 库纯净契约(硬约束,优先级最高)
|
|
453
|
-
|
|
454
|
-
> 库不得引用项目内容;项目用库只做"参数绑定/触发/定位",不自写或修改特效渲染。
|
|
455
|
-
|
|
456
|
-
1. **库(`packages/*`)禁止 import 任何项目代码**。仅允许:`@babylonjs/*` 等第三方 npm、库内相对路径、库自身模块。
|
|
457
|
-
2. **特效 ↔ 宿主唯一通道 = `create(context)`**(`scene/root/position/rotationY/renderingGroupId/params` + 必要时注入 `assetResolver`/锚点回调)。
|
|
458
|
-
3. **资源自带**:贴图/着色器/GLB/runtime-js 放包内,`?url`/相对导入;glTF loader 从 `@babylonjs/loaders` 引。
|
|
459
|
-
4. **配置参数化**:特效需要的配置值必须是 `defaultParams`/`debugParams`,经 `playEffectPackage(id, params)` 传入。
|
|
460
|
-
5. **项目侧只允许**:注册(glob)、触发、定位/挂载(transform)、传参、调参面板。**不得自写/改特效渲染。**
|
|
461
|
-
|
|
462
|
-
**保证机制**:`validate-manifest` 加 import 边界静态检查并入 CI;库 `package.json` 不依赖任何项目包(node_modules 边界物理强制——这也是选 C 的原因)。
|
|
463
|
-
|
|
464
|
-
## 18. 复用 `@fps-games/editor` 发布蓝图(不自己造)
|
|
465
|
-
|
|
466
|
-
核实结论:跨独立 repo 的 ESM 包消费 + Babylon dedupe + dev/versioned 双模式,**editor 已产品化**,VFX 照搬。
|
|
467
|
-
|
|
468
|
-
### 18.1 已验证的现成机制
|
|
469
|
-
- `@fps-games/editor`:`type:module` + `exports` 子路径 + `files:["dist"]`;内部多包用 `scripts/prepare-single-package.mjs` + `bundleDependencies` **打成单包发布**。
|
|
470
|
-
- Babylon:包里 `@babylonjs/core: ^8`(宽 range)+ 消费方 pin 精确版本 + 消费方 vite **`dedupe:['@babylonjs/core','@babylonjs/loaders']`** → 单实例。
|
|
471
|
-
- 双模式:`FPS_GAME_EDITOR_REPO` 在→别名到本地源码;不在→用 node_modules 版本包。
|
|
472
|
-
|
|
473
|
-
### 18.2 VFX 照搬
|
|
474
|
-
- 发 `@fps/vfx`(单 ESM 包,内含 runtime 核心 + adapters + dataEffect + buildRegistry + `effects/*`);`exports`:`.`、`./effects/<id>`、`./vite`。
|
|
475
|
-
- 消费方:pinned dep + vite babylon dedupe + `FPS_VFX_LIBRARY_REPO` 双模式。
|
|
476
|
-
- 资源随包:构建把贴图/GLB/shader emit 到 dist,经 `?url` 从安装包解析(Vite 标准能力,需配 build)。
|
|
477
|
-
|
|
478
|
-
### 18.3 alias 工具:克隆,不直接 import(已核实)
|
|
479
|
-
editor 的 `aliases.ts` 把包清单**写死在模块常量**(`PLAYABLE_EDITOR_PACKAGE_IDS`/`SOURCE_ALIAS_FILES`/`BUNDLED_ALIAS_FILES`),builder 不收包列表入参 → **不能直接调用**。**采用方案 1:克隆** `aliases.ts` 成 VFX 版,换那 3 个常量数组(`@fps/vfx-*` + bundled 根 `node_modules/@fps/vfx`),其余逻辑原样;`types`/`inspect...`/`collectMissing...` 这些**吃 plan 数据、与包无关的**直接从 editor SDK 复用。
|
|
480
|
-
|
|
481
|
-
## 19. 项目侧 VFX 耦合点 → 纯净化整改清单(实测)
|
|
482
|
-
| 违规 | 整改 | 状态 |
|
|
483
|
-
|---|---|---|
|
|
484
|
-
| `effects/lumber-debris-scatter/index.ts` import `projectGameplayConfig` + 资产注册 + `core/babylon-gltf-loader` | 自带 GLB 改 `?url` 加载;loader 从 `@babylonjs/loaders`;config 值挪进 params | ☐ |
|
|
485
|
-
| `SceneVfxService.createParticleSystem` 绑 `configService`+`UIImages`(legacy 场景粒子路径) | 移出库(改成普通特效包,项目 init 触发)或改注入 | ☐ |
|
|
486
|
-
| `renderingGroupId=2` magic(VFX 与 gameplay 共用) | 库导出 `VFX_RENDERING_GROUP_ID`,项目引库常量 | ☐ |
|
|
487
|
-
| gameplay 内联视觉(`WorkerAutomationSystem` 标记/`WaterSurfaceSystem`/`PayAreaDecalAmountSystem`/`StackVisualSystem`)+ truck `src/vfx/intro` 在包外 | intro 等真特效封装成合规库包;markers/water 等先界定纳不纳入库 | ☐ |
|
|
488
|
-
| 已合规:systems 的触发/`root.parent` 跟随/动态参数 | —— | ✅ |
|
|
489
|
-
|
|
490
|
-
## 20. 修订版总计划与剩余任务(勾选状态以本次实跑为准)
|
|
491
|
-
|
|
492
|
-
| 任务 | 说明 | 状态 |
|
|
493
|
-
|---|---|---|
|
|
494
|
-
| glob 自动发现(机制) | 两项目 barrel 改 glob;order 含 prod 门控 | ✅ 已做并实跑验证 |
|
|
495
|
-
| 机制全量迁移 | 两项目全部 23 特效跑在 glob | ✅ |
|
|
496
|
-
| 前后对比验证 | exhaust 同项目无损 + 跨项目复用 | ✅ |
|
|
497
|
-
| **`@fps/vfx` 真共享包** | 单 ESM 包、exports、babylon `^8`、单包打包(§18.2) | ☐ |
|
|
498
|
-
| **runtime 抽成库并被项目消费** | 去掉项目内 runtime 三份拷贝,改 import 包 | ☐ |
|
|
499
|
-
| `dataEffect.ts` / `adapters/` / `buildRegistry` 入库 | 重命名 + 统一持有 | ☐ |
|
|
500
|
-
| **混合分发(C)** | 项目改 re-export 桩 + 本地 params;`FPS_VFX_LIBRARY_REPO` 双模式 | ☐ |
|
|
501
|
-
| **克隆 VFX 版 alias 工具**(§18.3) | 换 3 常量数组 | ☐ |
|
|
502
|
-
| **库纯净契约整改**(§19) | debris / SceneVfxService / renderingGroupId | ☐ |
|
|
503
|
-
| **`validate-manifest`(含 import 边界检查)** | 进 CI | ☐ |
|
|
504
|
-
| **`generate-index` → `index.json`** | 顶层目录 | ☐ |
|
|
505
|
-
| **`vfx add` / `vfx update` CLI** | add + 升级安全(留 params、hash 检测) | ☐ |
|
|
506
|
-
| **pa_template 集成** | 替换弱版 SceneVfxService、glob、面板、`/__debug_panel_config` | ☐ |
|
|
507
|
-
| 旧库 6 个 Cocos 包迁入统一格式 | index.ts 薄包装 + ?url + tunableParams→debugParams | ☐ |
|
|
508
|
-
| **新建 pa_template 测试项目 E2E**(§21) | 生成新项目 + GLB + 特效验证 | ☐ |
|
|
509
|
-
|
|
510
|
-
## 21. 验证计划:用 pa_template 生成新测试项目 + GLB/特效测试
|
|
511
|
-
|
|
512
|
-
**目标**:在一个**全新、干净**的 pa_template 项目上,端到端验证「装库 → 导入特效 → 导入 GLB → 跑起来看到效果」,证明库对新项目开箱可用(而非只对两个老项目)。
|
|
513
|
-
|
|
514
|
-
步骤:
|
|
515
|
-
1. **生成新项目**:用 pa_template 脚手架建 `workspace/vfx-smoketest`(或按模板的 scaffold 流程);`pnpm i` 起 `pnpm dev`。
|
|
516
|
-
2. **接库**:装 `@fps/vfx`(或 `FPS_VFX_LIBRARY_REPO` 指向本地库源)、加 vite babylon dedupe + VFX alias、按 §16 在 `src/assets/vfx/effects/<id>/` 放 re-export 桩(由 `vfx add` 生成)。
|
|
517
|
-
3. **加几个 GLB**:从 `lumber-order` / `lumber-truck` 拿现成 GLB(如 `lumber-debris-scatter/assets/models/*.glb`、场景道具 glb),按 pa_template 的资产流程(`scripts/register-asset.mjs` + asset-catalog)注册,放进场景。
|
|
518
|
-
4. **加几个特效**:`vfx add` 几个干净特效(如 `vehicle-exhaust-smoke` 等;mesh 类待 debris 纯净化后再加),挂到 GLB 节点或固定点。
|
|
519
|
-
5. **测试**:`pnpm dev` 起,确认 ① 特效经 glob/桩自动发现并在面板出现;② 能播放、渲染正确;③ GLB 正常加载显示;④ 调参存回项目 `vfx-params.json`;⑤ 升级演示:bump 库版本,代码更新而项目 params 不丢。
|
|
520
|
-
6. **截图存档** + 结论同步 issue。
|
|
521
|
-
|
|
522
|
-
验收:**新项目无需手写任何渲染代码,仅靠装库 + 参数绑定即得到可调试的特效 + GLB 场景**(= 纯净契约 §17 的活体证明)。
|
|
523
|
-
|
|
524
|
-
---
|
|
525
|
-
|
|
526
|
-
*v2 由实跑验证 + 三项设计决策(依赖分发 C / 纯净契约 / 克隆 alias)收敛而成。§16–§21 优先于 §1–§15。*
|
|
527
|
-
|
|
528
|
-
---
|
|
529
|
-
|
|
530
|
-
## 22. 完成状态(实跑核验,2026-06-26)
|
|
531
|
-
|
|
532
|
-
**核心目标达成:`@fps/vfx` 成为纯净可消费共享包,并在全新 pa_template 项目端到端验证通过。**
|
|
533
|
-
|
|
534
|
-
### ✅ 已完成(实跑核验)
|
|
535
|
-
- `@fps/vfx` 单 ESM 包:`package.json`(exports `.`/`./effects/*`/`./vite`,babylon `^8` peer)+ `packages/index.ts` barrel。
|
|
536
|
-
- runtime 解耦:`EffectPackageService`/`SceneVfxService` 注入式 registry(`buildRegistry`);`generation.ts`/`registry.ts`;`createDataDrivenEffectPackage` 别名。
|
|
537
|
-
- **库纯净契约:boundary 0**(`validate-boundary.mjs` PASS);`SceneVfxService` 去 legacy;`lumber-debris-scatter` 去项目耦合(自带 GLB `?url` + `@babylonjs/loaders`)。
|
|
538
|
-
- 运行期错误兜底(`create()` try/catch,坏包不崩场景)。
|
|
539
|
-
- 工具链:`validate-boundary.mjs`、`generate-index.mjs`→`index.json`(23)、`vfx-package-resolution.mjs`(克隆 alias)、**`vfx-cli.mjs`(`list`/`add`/`update`,含覆盖策略 + provenance)**。
|
|
540
|
-
- **§21 新项目 E2E(`workspace/vfx-smoketest`)**:全新 pa_template 项目装 `@fps/vfx`(dev-alias + vite babylon dedupe + `server.fs.allow` 库源)→ glob 经 re-export 桩自动发现 → `vehicle-exhaust-smoke` 正确渲染(贴图随包加载)→ `lumber-debris-scatter` 自带 **GLB 加载成功**(11 块 mesh)→ `vfx add player-upgrade` 后 reload 自动发现(4 特效,零手动注册)。无 VFX 报错。
|
|
541
|
-
|
|
542
|
-
### ⏳ 剩余(非阻塞)
|
|
543
|
-
- 旧两个项目(lumber-order/truck)目前用各自 runtime 拷贝 + glob;迁移成消费 `@fps/vfx` 包(去掉拷贝)留作后续。
|
|
544
|
-
- 旧库 6 个 Cocos 数据包(`build.particle.*` 等)迁入统一格式。
|
|
545
|
-
- `adapters/` 统一持有(现 per-package 自带运行时 js);`validate-boundary` 接入实际 CI 配置文件。
|
|
546
|
-
- 一次性/data 特效的「干净定格」截图(harness 时机局限;功能已验证)。
|