mcpField
S
scenario-unity-vfx

scenario-unity-vfx

github.com/scenario-labs创意与媒体1.2k266 次安装1 天前更新
代码仓库

关于 scenario-unity-vfx

面向 Unity 实时特效创作的技能,供游戏 VFX 艺术家及开发者使用。它将游戏可读性、性能预算与逐帧验证结合,并涵盖 Shuriken 和 VFX Graph 工作流。

主要功能

  1. 01按玩法重要性设计特效层级
  2. 02选择 Shuriken 或 VFX Graph
  3. 03构建材质、纹理与特效
  4. 04逐帧检查并测量开销
  5. 05验证批处理、剔除与粒子数量

适用场景

  1. 01制作移动端冲击波与爆炸
  2. 02检查多份特效同时出现时的可读性
  3. 03分析过绘制、粒子数与帧预算

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/scenario-labs/skills --skill scenario-unity-vfx

安装后在 Claude Code 中输入/scenario-unity-vfx确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
critique.md
expert-notes.md
gui-paths.md
procedures.md
sources.md
scripts/
ut_vfx.py
scripts/AgentKit/Vfx/
VfxAudit.cs
VfxBudget.cs
VfxFireballKit.cs
VfxGraphJobs.cs
VfxMaterials.cs
VfxMeshes.cs
VfxMeshFx.cs
VfxSequence.cs
VfxShuriken.cs
VfxStress.cs
VfxTextures.cs
VfxUber.cs
scripts/EditorGraph/
Unity.Testing.VisualEffectGraph.EditorTests.asmdef
VfxGraphAuthoring.cs
scripts/EditorGraph/Sdf/
AgentKit.Vfx.GraphTools.asmdef
VfxSdf.cs
scripts/Runtime/
AgentKit.Vfx.Runtime.asmdef
scripts/Runtime/Vfx/
FireballProjectile.cs
VfxStressSpawner.cs
VfxTier.cs
scripts/Shaders/
VfxOverdraw.shader
VfxUber.shader

详细介绍

Unity VFX(实时特效美术)

专业特效首先服务于游戏:在目标设备上,以屏幕上实际显示的副本数量,让玩家看清发生了什么、危险在哪里、何时结束。这里会同时衡量制作水准(层次、对比度、运动、纹理)和预算(填充率、粒子、绘制调用、内存):每个特效都会在屏幕外逐帧运行、检查并计数。目标环境:Unity 6000.3.21f1、URP 17.3、VFX Graph 17.3.0、macOS Apple Silicon。如果此处提到的同级技能不在你的可用技能中,请让用户安装它(npx skills add scenario-labs/skills --skill <name>);如果无法等待,请根据工具架构继续操作并标明这一缺口。

必备背景: scenario-unity-expert(通道、审查循环、6.3 陷阱、ut_run、ut_review、ut_stat、AgentKit)。

状态(2026-09-24,盲评重构后): 所有流程均已通过 tests/code/unity-vfx/ 在 Unity 6000.3.21f1 中运行(结果见 archive/tests/unity-vfx/live_results.jsonl,数据见 references/procedures.md)。

核心立场(专家之见)

  1. 玩法优先于美观(Jason Keyser,前 Riot)。主形状就是玩法边界;亮度应按重要性分配预算(待机和普通攻击应低调,改变战局的效果和终极技能应明亮);效果应在玩法状态结束时一并结束;应使用 N 个副本进行评审,而非只看一个。为每个根节点标记 VfxTier,并检查层级(ut_vfx.importance_ladder;观测值:斩击 0.39 < 枪口火光 0.46 < 命中 1.50 < 冲击波 2.60 < 爆炸 5.99)、人群可读性(crowd_readability:在符合玩法间距的情况下,20 个爆炸看起来是 20 个形状;间距压缩到 2.2 m 时则只有 6 个),以及停止后的尾迹。
  2. 在移动端,让纹理在网格上移动胜过粒子云(Nikola Damjanov,Nordeus:已发布效果中约 90% 如此;粒子只是点缀,每个发射器最多 100 个;过度绘制的影响大于绘制调用)。观测结果:同一个冲击波使用单个环形网格时,到处都只绘制 1 层,峰值为 0.037 个全屏等效值(FSE);而在覆盖区域内会绘制 5 到 7 层,36 个喷溅则达到 0.35 FSE。应测量每帧的填充量,而非粒子数量。
  3. 根据平台和数据流选择系统。 对于每个目标手机、WebGL、逐粒子 C#、Unity 物理碰撞:使用 Particle System,并逐个模块脚本化。对于数千到数百万个 GPU 粒子、深度缓冲区碰撞、贴花、六向烟雾、GPU 事件:使用 VFX Graph;它需要 compute,仅能在部分高端 URP Android 设备(电子书)上运行,在 Web 上则只能通过 WebGPU 运行,该功能在 6.3 中仍处于实验阶段。
  4. 使用一个超级材质,通过 Custom Data 提供逐粒子数据。 Nordeus 的超级着色器:灰度 R 通道通过 LUT 渐变着色,G 通道用于自发光,B 通道用于覆盖 Alpha,另有线性淡出、侵蚀、第二 Alpha、每种材质各自的 Blend 和 Cull。AgentKit/VFX/Uber 是以文本形式提供的该着色器;每个实例的变化(侵蚀曲线、随机 UV 偏移、擦除)通过 Custom Data 模块和自定义顶点流提供(Hovl Studio:“无法在着色器中生成随机数”),因此所有变体都能共用一种材质,并保持 SRP Batcher 启用。流顺序是审计检查的约定。
  5. VFX Graph 是带有公开 API 的黑盒(VFX Graph 电子书;Orson Favrel,Unity)。复制模板,公开少量属性和事件,并通过缓存的 ID 驱动;命令会延迟执行,而 aliveParticleCount 在首次读取前会返回 -1,此后每 60 帧刷新一次(观测结果)。内存用量为容量 × 存储属性;包围盒决定剔除;排序需要一次 dispatch;若粒子只需要位置则使用点缓存,若需要贴合或碰撞则使用 SDF(两者均可脚本化,P8、P12)。
  6. 分层设计,每层各司其职,并注意对比、顺序和运动(Sirhaian、Gabriel Aguiar、Nordeus)。将深色 Alpha 主体置于加法混合的热度层之下,并为堆叠的 Alpha 层设置不同排序顺序;除循环外,不使用线性曲线;混合快慢元素;循环开始时加入爆发效果;始终让某些元素保持运动;变体贴图表应让每个粒子随机选取一个固定帧播放,绝不作为动画播放;火花应逐渐缩小,而火焰应逐渐增大;每层都应淡入淡出。
  7. 能借用或计算的就不要绘制;按画面显示尺寸导入(Simon Trümpler;Nordeus 常用 256,最大 512)。借用的翻页纹理应进行混合,并采用减速的帧曲线;简单形状应直接生成;精灵应通过运动模糊而非高斯模糊获得柔和边缘,并避免让取值落在边框上;通道打包的数据纹理应以线性方式导入(若按 sRGB 处理,0.5 灰度读出的值为 0.21,观测结果);LUT 应保持未压缩。
  8. 在 6.3 中,Shader Graph 粒子着色器会悄然关闭网格粒子的 GPU 实例化(Fred Moreau,Unity):5,000 个立方体的主线程耗时增加 69%,但绘制调用相同(观测结果)。审计会标记此问题;修复方案来自 scenario-unity-shaders。

先明确需求

只询问一次:目标档位和帧预算(移动端默认 30 fps、65% 占比 = 21.7 ms);可用算力;最低档位是否启用后处理(不使用 Bloom 时,需通过叠加层伪造辉光);游戏摄像机和距离;每种特效的重要性档位、频率、伤害半径和持续时间;最坏情况下屏幕上的副本数(默认 20);三个特效支柱(Keyser);世界是否受光照,以及一天中的时段。默认值:URP、Shuriken、移动端优先使用网格、低档位不启用后处理、预算为 ut_vfx.BUDGETS["mobile"]。

工作流

  1. 用数字说明需求。 档位、半径、持续时间、副本数、预算。GATE:后续每项检查都有阈值(ut_vfx.BUDGETS,标记为来源值或 [added])。
  2. 选择系统和骨架(Stance 2、3)。Shuriken:每个层级调用一次 VfxShuriken.Build(parent, Layer, seed);网格层级设置 Layer.mesh(VfxMeshes.Ring、Cone、QuadXZ、Color32 顶点 alpha)。VFX Graph:调用 VfxGraphJobs.CopyTemplate,然后在 GUI 中公开属性(references/gui-paths.md);若不受支持,则调用 VfxGraphJobs.Author。GATE:VfxGraphJobs.Contract 列出游戏逻辑使用的每个属性和事件。
  3. 纹理和材质。 使用 VfxTextures.ImportVfxTexture(Clamp、按档位设置尺寸;数据纹理关闭 sRGB);通过 VfxMaterials.Particle 创建 URP 粒子材质(通过 BaseShaderGUI.SetMaterialKeywords 执行检查器逻辑);通过 VfxUber.Create(path, UberSpec) 创建 uber 材质,并在资源上设置关键字,绝不在运行时切换。火焰、火花、拖尾和魔法特效保持无光照;烟雾和尘土使用 Simple Lit,或在光照会变化时使用六向着色;URP 粒子着色器不投射阴影。GATE:渲染队列 3000、预期的关键字、无洋红色、无 Built-in 着色器(审计)。
  4. 构建特效。 完整示例:VfxFireballKit.Build(投射物、枪口、带焦痕和炽热核心的撞击、爆炸)和 VfxMeshFx.Build(网格冲击波、粒子冲击波、使用 Custom Data 的斩击)。Custom Data:Layer.custom1X/custom1Y/custom2X/custom2Y(曲线或随机范围)设置模块和 VfxUber.Streams。生成代码调用 VfxSeed.Reseed(go):固定种子仅用于截图。GATE:VfxAudit.AuditPrefabs 报告 0 个错误;说明所有警告。
  5. 逐帧查看并评审效果。 使用 VfxSequence.CaptureEffect(适用于任意预制体:副本使用不同种子,循环使用 stop_t,着色器时间固定为模拟时间)或 CaptureFireball;运行 ut_review.review_images;打开联系表。GATE:没有空白帧或洋红色帧;references/critique.md 中的 A 和 B 均通过。
  6. 测量。 使用 VfxBudget.Overdraw(每像素层数、FSE、热力图)、Counts、VisualRadius(考虑网格)、ScreenTexel;运行 ut_vfx.effect_verdict 或 sequence_verdict、texel_verdict、对整组效果运行 importance_ladder,以及在游戏间距下对 VfxStress.StressOverdraw 运行 crowd_readability、对间隔均匀的循环帧运行 motion_gaps;使用 AgentKit.AgentProfile.PlayModeTimings 对照 0 个副本的场景运行压力测试档案。GATE:判断结果通过,或以书面理由说明警告;帧时间增量在 VFX 占用预算内。
  7. VFX Graph 运行时检查(VfxGraphJobs.PlayTest):离屏摄像机目标、属性 + 事件、延迟帧后的数量、批处理的 N 个实例、转向后被剔除;运行 ut_vfx.graph_hygiene(vfx_yaml_facts(...), peak_alive)。GATE:数量与公开的速率成正比,unbatchedInstanceCount == 0,两个方向均能正确剔除,容量接近存活数量。
  8. 修复一项问题,重新运行第 5 至 7 步并进行对比(ut_review.compare,并排查看热力图)。提交时附上证据(采用 scenario-unity-expert 报告格式)。

数值

数值对应来源
约 90%在网格上移动的纹理效果(移动端)Nordeus
100每个发射器的粒子数上限(移动端)Nordeus
8 到 10 / 5 到 6 / 2 到 3高级 / 低级 / 多目标 SPELL 的绘制调用数(按玩法等级,而非设备档次)Nordeus
典型值 256,最大值 512;LUT 未压缩VFX 纹理导入(移动端)Nordeus
0.1 到 0.2 s;0.15 到 0.2 s枪口和闪光的持续时间;快速弹丸的拖尾时间Gabriel Aguiar
约 0.3 s斩击持续时间(即挥砍动作)Hovl Studio
焦痕 1.75 到 2,热核心 0.75 到 1.3命中表面上的两个叠加痕迹Gabriel Aguiar
50 units/sVFX Graph 的按距离生成阈值17.3 source
0.5 s;0.5 到 4玩法停止后的拖尾时长;粒子上的纹素数 / 其屏幕像素数(详细纹理)[added]
1 层对比 5 到 7 层,0.037 对比 0.35 FSE峰值时的环形网格与 36 团烟尘冲击波,分辨率为 960 x 540observed
0.51 FSE,p95 11,98 个粒子火球套件在峰值时的表现(移动端档次)observed
1.05 FSE,540 个粒子;CPU +0.22 ms20 次爆炸在峰值时的表现;同时回放与不回放的对比(编辑器中,仅供参考)observed
0.89 对比 1.51 ms5,000 个网格粒子:URP Particles/Unlit 对比 6.3 Shader Graph 粒子模板observed

质量门槛

  • 可测量: 审核 counts.error == 0;效果或序列结论为通过,或对警告作出说明 (填充、粒子、视觉 / 玩法半径 0.85 到 1.2、窗口结束后粒子数为 0、拖尾低于 0.5 s);阶梯测试通过;人群测试在玩法间距下通过;纹素结论;压力测试增量;VFX Graph 契约、 数量、批处理、剔除、整洁性。
  • 视觉: 已打开接触表;飞行中的弹头最亮;没有被几何体裁切;各层逐渐淡出; 热力图热点与可见内容相符;连续实例之间有所不同。

常见错误

错误表现修复方法
本可使用网格,却使用了粒子云(移动端)一个圆环使用了 5 到 7 层重叠效果(观察所得)使用圆环或圆弧网格 + 滚动的 uber 材质,1 层
使用自定义数据,却没有匹配的数据流着色器读取到零值:没有侵蚀效果,也没有热启动(观察所得)VfxUber.Streams;检查 vfx.stream_mismatch
将通道打包纹理按 sRGB 导入效果变暗、出现侵蚀关闭 sRGB;检查 vfx.data_texture_srgb
网格粒子网格上的顶点颜色使用浮点数呈现暗蓝色、平坦效果,Alpha 为 0.25;MeshRenderer 则正常(观察所得)Mesh.SetColors(List<Color32>);检查 vfx.mesh_color_format
使用线性尺寸或侵蚀曲线动作机械;v0.1 工具包中有 6 个此类曲线(观察所得)使用 EaseOut/EaseIn/Decelerate;检查 vfx.linear_curve
将变体图集作为动画播放所有粒子同时切换形状随机固定帧:Frame over Time 在两个常量之间随机取值
在透明效果之后绘制其周围的扭曲效果下方的辉光消失(剩余 31%,观察所得)先绘制扭曲效果:降低渲染顺序或增大 Sorting Fudge
发布时工具包种子固定每次效果完全相同生成时调用 VfxSeed.Reseed
高射速时每次效果都执行 Instantiate 和 Destroy分配峰值使用对象池:调用 Clear + Play 重播(VfxStressSpawner),在加载时预热
近距离爆炸占满屏幕全屏填充率峰值Renderer Max Particle Size(工具包:移动端为 0.35)[已添加]
烟团或闪光效果以命中点为中心与表面之间出现明显的直线切口沿法线偏移(移动端)或使用软粒子(PC)
叠加的 Alpha 图层使用相同的排序顺序闪烁使用不同的顺序,并将辉光置于最上层
URP 中仍保留旧版粒子材质仍能绘制,因此无人察觉;但没有 URP 功能使用 VfxMaterials.MigrateLegacyJob,比较捕获结果
在发送帧断言 VFX Graph 数量数值为 -1 或已过期等待延迟帧及 60+ 帧
在未限制帧率的批处理 Play 模式中进行性能分析300 帧仅相当于 0.3 秒的效果设置 Time.captureDeltaTime = 1f / 60f,运行 600 帧

更多条目(VFX Graph 组合、事件、拖尾、捕获陷阱):见 references/critique.md 的 F 节。

交接

  • 接收:来自 scenario-unity-gameplay:命中点和法线、伤害半径、投射物速度、射速;来自 scenario-unity-shaders:溶解、拖尾、实例化 Shader Graph 粒子、对 AgentKit/VFX/Uber 的变体评审;来自 scenario-textures 或 scenario(Scenario MCP):翻页纹理和遮罩,用于加法混合的黑底灰度图;来自 scenario-unity-rendering-lighting:各档 Bloom、各档 Depth 和 Opaque Texture(软粒子、扭曲)、Decal 功能。
  • 交付:给 scenario-unity-gameplay:带有 VfxTier 的预制件、类似 FireballProjectile 的衔接代码、效果约定;给 scenario-unity-performance:压力测试场景、CSV、热力图;给 scenario-unity-mobile:各档预算和删减项(优先删减最不重要的层);给 scenario-unity-web:仅在 WebGPU 构建中使用 VFX Graph。
  • 数据包:项目、渠道、用数字描述的简报、作业 ID、联系表和热力图、结论行、Verified、Assumed。

Unity 6.3 注意事项

  • VFX Graph 17.3.0 是核心包;模板 01_Minimal_System 到 06_Firework 不公开任何内容;已弃用:带模式的 Trigger Event 区块、Set Position Shape、Collision Shape、Set Position From Source、Output Particle URP Lit Decal;YAML 中的输出排序为 Auto、Off 或 On(0、1、2)。
  • SetActiveVertexStreams 取代了 EnableVertexStreams;URP 粒子着色器没有 ShadowCaster 通道,并且翻页纹理混合时不使用运动矢量(VFX Graph 有 Flipbook Motion Blend):为主角或慢速元素保留带运动矢量的翻页纹理(Nordeus);URP 扭曲会采样不包含透明物体的 opaque texture。
  • 6.3 之后:6.5 弃用动态批处理,6.6 将其废弃;6.6 新增 Shader Graph Preprocessor Directives 和粒子节点;WebGPU 在 6.6 中脱离实验阶段。

参考资料

  • references/expert-notes.md:专家原则及其时间戳、分歧和判定条件。
  • references/procedures.md:P0 到 P19,包含可复制的代码及其实际结果。
  • references/critique.md:自我评审标准(玩法、工艺、预算、VFX Graph、诚信)和完整的错误表。
  • references/gui-paths.md:通过窗口和菜单完成相同工作的步骤。
  • references/sources.md:所有来源、凭据、URL、最佳时间戳、修订历史。
  • scripts/ut_vfx.py(预算、结论、阶梯、群集、纹素、运动间隙、Graph 卫生检查、.vfx 事实、pCache);scripts/AgentKit/Vfx/(作业、uber 材质、网格、mesh-first 工具包);scripts/Runtime/(压力生成器、投射物衔接代码、VfxTier、VfxSeed);scripts/Shaders/(VfxUber.shader、VfxOverdraw.shader);scripts/EditorGraph/(不受支持的 Graph 编写、SDF 烘焙)。

评论

支持 Markdown