DreamFXLang

概览

DreamFXLang 是 Unreal Niagara 特效的文本化语言,由 DreamFX 插件编译成标准 Niagara 资产,并能把现有系统反编译回源码。

DreamFXLang 是 Unreal Engine Niagara 特效的文本化语言。你写 .dfs.dfe.dfm 文件, DreamFX 插件把它们编译成标准资产 —— UNiagaraSystemUNiagaraEmitterUNiagaraScript —— 关卡、蓝图、Sequencer 引用它们的方式和引用任何别的资产完全一样。

源文件才是你维护的东西。.uasset 是构建产物,随时可以扔掉重建,不手改。

反方向同样成立:任何现有 Niagara 系统都能反编译回 .dfs。这不是便利导出,是有契约的往返 —— 语言表达不了的东西逐条写进文件头缺口注释,绝不静默丢弃。

插件版本1.0.0
引擎Unreal Engine 5.8(自维护源码引擎与预编译安装版同一份源码零 #if 分叉
模块DreamFX(Runtime)、DreamFXEditor(Editor)
源文件扩展名.dfs · .dfe · .dfm
项目设置Project Settings ▸ Plugins ▸ DreamFX
诊断码143 个 DFXnnnn,全带文件 / 行 / 列
许可证MIT

三种源文件

扩展名声明产物
.dfsSystem一个 UNiagaraSystem
.dfeEmitter自身不产资产 —— 由 .dfsfrom 拷入
.dfmModule / DynamicInput一个 UNiagaraScript(预编译引擎经反射后端同样可用)

三者共用一个文件头:

<Kind>(Name="<相对内容根的路径>", Root="<根记号>")
{
    ...
}

Kind 必须与扩展名一致(DFX2021)。RootGame、 空串(同义)或 Plugin.<插件名>Name 是相对那个内容根的资产路径。详见 文件模型

最小系统

System(Name="Effects/NS_Hello", Root="Game")
{
    Properties = {
        float Speed = 150.0 [ Group="Motion" ];   // 暴露为 User.Speed
    }

    Emitter Motes
    {
        Settings = { SimTarget = CPU; Determinism = true; RandomSeed = 1; }

        EmitterUpdate = {
            EmitterState(LifeCycleMode = Self, LoopBehavior = Infinite);
            SpawnRate(SpawnRate = 20.0);
        }

        ParticleSpawn = {
            Spawn/Initialization/V2/InitializeParticle(
                LifetimeMode = DirectSet, Lifetime = 2.0,
                SpriteSizeMode = Uniform, UniformSpriteSize = 8.0
            );
            SystemLocation();
            AddVelocityInCone(ConeAngle = 30.0, VelocityStrength = User.Speed);
        }

        ParticleUpdate = {
            ParticleState();
            GravityForce(Gravity = (0, 0, -400));
            SolveForcesAndVelocity();
        }

        SpriteRenderer Core
        {
            Alignment = Unaligned;  FacingMode = FaceCamera;  SortMode = ViewDepth;
        }
    }
}
pwsh -File Plugins/DreamFX/.skill/dfx.ps1 build DFX/Effects/NS_Hello.dfs

生成 /Game/Effects/NS_Hello,全程不需要打开编辑器。编辑器开着时,存盘即重建 —— 把生成的资产在 Niagara 编辑器里开着,它就是这套文本工作流的实时预览。

写包的命令(buildcorpusmirror-diffdecompile-all要关掉编辑器。 两个进程存同一批包,谁后存谁赢,而且两边都不吭声。见日常循环

语言覆盖到哪里

  • user 参数,含带 JSON 配置的数据接口参数(DI<X>);
  • 六个固定栈SystemSpawn / SystemUpdate / EmitterSpawn / EmitterUpdate / ParticleSpawn / ParticleUpdate
  • 事件处理器 OnEvent(...)具名 simulation stage Stage <Name>(...)
  • renderer 的 schema 驱动属性与 Bind 绑定;
  • 全部值形态:字面量、linked、枚举、嵌套 dynamic input、hlsl { }、带切线模式的 curve { }, 以及所有位置的静态开关。

不覆盖的(设计使然或尚未做):Scratch Pad、模块内部图 lowering、GPU/CPU 条件分支、 Scalability 条件逻辑、真正的 emitter 继承(from 是拷贝)。降级全部有诊断,绝不静默 —— 见能力边界

四层往返验证

反编译的正确性不是声称的,是量出来的:

回答什么问题
L1 mirror-diff镜像的导出与原件的导出逐行相同吗?
L2镜像编译干净吗?
L3重建的系统模拟起来和原件一样吗?(固定步长 SimCache 逐帧粒子数)
asset-diff两个资产作为资产一致吗?—— 不经导出器的反射走查,含编译器自己的视角

细节见往返与等价

从哪里开始

本页目录