DreamFXLang
快速上手

DreamFX 是什么

它做什么、不做什么,以及几条贯穿始终的设计立场:文本是唯一真相、缺口必须显形、菜单不是第二套实现。

DreamFX 把文本编译成标准 Niagara 资产,并把标准 Niagara 资产反编译回文本。范围仅此而已 —— 它不是一个新的粒子运行时,也不是 Niagara 的替代品。生成出来的东西就是普通的 UNiagaraSystem / UNiagaraEmitter / UNiagaraScript:任何引擎加载它、任何 .dfs 引用它、 cook 它、跑它,都和手连出来的没有区别。

为什么要写成文本

Niagara 的编辑面是图和栈。图很好用,直到你需要:

  • diff 一次改动 —— 谁把 spawn rate 从 20 改成 60 了?二进制资产回答不了;
  • 批量改 40 个特效 —— 手点 40 遍,还是改 40 个文本文件?
  • code review —— 一个 .uasset 的 PR 只能看结论,看不到过程;
  • 让代理去做 —— 一个编码代理能写文本、跑构建、读诊断;它点不了 Slate 按钮。

文本化不是为了更"高级",是为了让版本控制、批量操作和自动化这三件事重新变得可能。

几条设计立场

文本是唯一真相,资产是构建产物

生成的资产上盖着溯源戳(源 hash + 生成器版本 + 模块版本 GUID)。手改它,下次重建铲掉; 改了源码不重建,verify 会把它抓出来。资产随时可以删掉重建,这句话必须一直是真的, 否则整个模型就塌了。

缺口必须显形,绝不静默丢

反编译一个 DreamFXLang 表达不了的东西时,它不会悄悄丢掉:那一条会写进导出文件的头部缺口注释, 并以一个 DFX8xxx 警告的形式报出来。Adopt 更严 —— 有任何缺口就直接拒绝接管。

一个静默降级的工具会让你在三个月后对着一个不对劲的特效发呆,而且没有任何线索。

菜单是入口,不是第二套实现

编辑器里每一个按钮都调用 commandlet 调用的同一份代码。Rebuild DFX 能用,dfx build -All 就能用,反之亦然。而且每个命令都能从 Python 调 —— 只有人手能点到的命令,是永远得不到回归测试的命令。

声称要能被测量

「反编译是无损的」这种话不算数,除非有个东西能把它证伪。所以有四层验证:文本逐行、镜像编译、 SimCache 运行时逐帧、以及绕开导出器的资产事实走查。第四层存在的理由很具体:前面几层比的是同一个 导出器的两份产物,导出器自己丢掉的东西,它们对称地看不见。

不做什么

Scratch Pad不表达。Scratch Pad 脚本是资产内嵌的图,没有稳定名字
模块内部图 lowering.dfm 的 body 落成一个 custom HLSL 节点,不铺成节点图(那是 DreamShader 已经有的那个约 1.3 万行的问题,重做一遍)
GPU/CPU 条件分支、Scalability 条件未覆盖
真正的 emitter 继承from拷贝。编辑 .dfe 不会反向影响已经拷过它的系统,直到它们重建
通用表达式编译器内联表达式只有算术和一张短白名单。要更多就写 hlsl { }.dfm

完整清单与 1.0.0 的已知问题在能力边界

和 DreamShader 的关系

DreamShaderLang 是同一个作者的姊妹项目,对材质做同一件事: .dsm / .dsf / .dsh 生成 UMaterialUMaterialFunction

两者共享设计立场(文本是源、诊断带位置、编辑器集成走同一条管线),但不共享代码, 语法也不通用。一个明显的分岔:DreamShader 有一个完整的表达式编译器,DreamFX 有意不做 —— Niagara 的模块生态已经把"计算"这件事解决了,DreamFX 的工作是把模块接起来, 而不是再发明一次算子。

名字与版本

插件DreamFX 1.0.0
语言DreamFXLang
模块DreamFX(Runtime)、DreamFXEditor(Editor)
commandlet-run=DreamFX
驱动脚本.skill/dfx.ps1.skill/ci.ps1
日志分类LogDreamFX
作者TypeDreamMoon · MIT

本页目录