DreamFXLang
插件参考Diagnostics

DFX7xxx —— 溯源、漂移与 lint

DFX7xxx —— 溯源、漂移与 lint

DFX7xxx —— 溯源、漂移与 lint

生成标记之间的区块由 .skill/gen-diagnostics.ps1 写入。 标记以下的内容全部由手工写入,并在重新生成后保留。

DFX7001

严重级别: 错误 (error)

消息:

Asset '%s' carries no DreamFX provenance stamp: it was never generated from this source, or it was created by hand.

触发位置: Source/DreamFXEditor/Private/Generation/DreamFXGenerator.cpp:5258, Source/DreamFXEditor/Private/Generation/DreamFXModuleGenerator.cpp:769

原因. 资产上没有溯源戳:它从来不是这份源码生成的,或者是手工建出来的。

修复. 跑一次构建。如果这个资产是手建的、而且应该保持手建,就不要让任何 .dfs 指向它的路径 —— 一次构建就会盖掉它。

DFX7002

严重级别: 错误 (error)

消息:

Asset '%s' is stale: it was generated from a different revision of this source. Run the DreamFX build.

触发位置: Source/DreamFXEditor/Private/Generation/DreamFXGenerator.cpp:5265, Source/DreamFXEditor/Private/Generation/DreamFXModuleGenerator.cpp:776

原因. 资产是照这份源码的另一个版本生成的。这就是那个没人会自己发现的情况:有人改了 .dfs、没重建、把两个都提交了。单跑一次构建会通过,因为构建会把它修好。

修复. 跑一次 DreamFX 构建,把资产和源码一起提交。

DFX7003

严重级别: 警告 (warning)

消息:

Asset '%s' was generated by DreamFX %s; the current generator is %s. A rebuild is recommended.

触发位置: Source/DreamFXEditor/Private/Generation/DreamFXGenerator.cpp:5272

原因. 资产是旧版生成器建的。同一份文本在生成器变更之后可能降成不同的资产,所以戳里记着版本。

修复. 重建。

DFX7004

严重级别: 错误 (error)

消息:

Asset '%s' does not exist: this source has never been built.

触发位置: Source/DreamFXEditor/Private/Generation/DreamFXModuleGenerator.cpp:1108

原因. -Verify 根本没找到这份源码对应的资产。

修复. 跑一次构建。

DFX7005

严重级别: 错误 (error)

消息:

(built at runtime)

触发位置: Source/DreamFXEditor/Private/Generation/DreamFXGenerator.cpp:5309, Source/DreamFXEditor/Private/Generation/DreamFXGenerator.cpp:5314

原因. R7 漂移。源码没变,资产也没变,但它们共同依赖的某个模块现在暴露出不同的版本 —— 也就是说,这个资产是照另一个模块建出来的,而不是这次构建会用的那个。源码和资产本身都不会说这件事,这正是戳里要记模块版本的原因。

修复. 重建以采纳新版本;或者用 @<version> 固定模块,让不匹配在调用点被报出来。默认是警告,因为一次引擎升级会同时打到所有源码,而重建就能解决;-StrictVersions 把它升成错误,用于发布门。

DFX7101

严重级别: 警告 (warning)

消息:

Emitter '%s' simulates on the GPU but declares no FixedBounds. GPU emitters cannot compute their own bounds, so it will use a default box and may be culled unexpectedly.

触发位置: Source/DreamFXEditor/Private/Lint/DreamFXLint.cpp:138

原因. GPU 发射器读不回自己的粒子位置去算包围盒,所以没有固定包围盒的话它会拿到一个默认盒子,镜头从某个角度看过去的瞬间它就消失了。

修复. 在发射器或系统上设置 FixedBounds = box(...)。

DFX7102

严重级别: 警告 (warning)

消息:

Emitter '%s' spawns by rate ('%s') with no upper bound. Set AllocationMode = Fixed and PreAllocationCount to cap the particle count.

触发位置: Source/DreamFXEditor/Private/Lint/DreamFXLint.cpp:151

原因. 按速率生成自己没有上限:一个长命发射器配自动分配估计会不断重新分配,而一个跑飞的速率没有东西拦得住它。

修复. 设置 AllocationMode = Fixed; 和 PreAllocationCount 给粒子数封顶。

DFX7103

严重级别: 警告 (warning)

消息:

Emitter '%s' uses randomness ('%s') but does not set Determinism = true, so it will look different on every play. Add Determinism and RandomSeed to its Settings if reproducibility matters.

触发位置: Source/DreamFXEditor/Private/Lint/DreamFXLint.cpp:164

原因. 没有固定种子的随机意味着每次播放效果都不一样。做环境氛围没问题,但对任何要被过场动画或测试拿去比对的东西都是错的。

修复. 在意可复现性就加上 Determinism = true; 和一个 RandomSeed。

DFX7104

严重级别: 警告 (warning)

消息:

This renderer has no Material and DreamFX knows no default for its type, so it will not draw. Set 'Material = \"...\";'.

触发位置: Source/DreamFXEditor/Private/Generation/DreamFXGenerator.cpp:4329

原因. 这个渲染器没有材质,而 DreamFX 也不知道它这个类型的引擎默认值,所以它什么都不画。

修复. 设置 Material = "...";

DFX7105

严重级别: 警告 (warning)

消息:

MeshRenderer OverrideMaterials is nonempty but material overrides are disabled. Set bOverrideMaterials = true; or remove OverrideMaterials to use the mesh's own materials.

触发位置: Source/DreamFXEditor/Private/Generation/DreamFXGenerator.cpp:1852

原因. 一个网格体渲染器的 OverrideMaterials 数组非空,而它最终的 bOverrideMaterials 设置为 false,所以 Niagara 会忽略这些覆盖。

修复. 将 bOverrideMaterials = true; 设为应用该数组,或移除 OverrideMaterials 以使用网格体自身的材质。

DFX7106

严重级别: 信息 (info)

消息:

pull: %s.%s is stored on the asset and not declared in this text -- skipped. pull adds no structure.

触发位置: Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:1755, Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:1878

原因. 资产的存储中存有某个输入的值,而文本并没有写入这个输入。pull 只重写调用已有的字面量,别的什么都不做:添加参数会改变文本所描述的结构,那是另一种改动、归另一个负责人 —— 构建安全门(DFX8017)才决定一次重建是否会丢掉这样的值。

这个列表天生就长。引擎会为每个模块的每个输入物化一个常量,所以这些行大多是模块自身的默认值坐在存储里;在本项目的内容上,一个系统报告了 94 条,其中 8 条是有人真正调过的值。

修复. 当这个值是模块默认值时,什么都不用做 —— 重建会复现它、什么也不丢,这也是为什么这些行是信息而不是失败。当它是被调过的值时(就是那些 DFX8017 会拒绝保存的值),把这个输入写进文本再跑一次 pull,或者用 decompile -NoDefaults 导出,它会打印出模块拥有的每一个输入。无论哪种方式,下一次 pull 就有字面量可以修正了。

DFX7107

严重级别: 信息 (info)

消息:

pull: '%s' already holds every value '%s' stores for the input(s) it declares (%d compared, %d not declared, %d not writable, %d withheld). No bytes written.

触发位置: Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:2355

原因. 比对下来没有任何东西要写:文本声明的每一个输入、资产为其存有值的每一个输入,都已经持有相同的值。比对是按值进行的,不是按字符 —— 文本的字面量会以一次构建完全相同的方式被降级,然后逐字节与存储比对 —— 所以 0 和存储中的 0.0 是吻合的,不会被改写成对方的写法。

修复. 什么都不用做。这就是这个命令围绕的不动点:对一个刚刚 pull 过的文件再跑一次 -Apply,会报告这一条,一个字节也不写。

DFX7108

严重级别: 错误 (error)

消息:

pull reads a .dfs and the Niagara system it names: '%s' declares a %s document.

触发位置: Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:907, Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:924, Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:935, Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:949

原因. pull 需要一个 Niagara 系统来读出值,它从文本自身的 Name=/Root= 取路径 —— 与一次构建使用完全相同的解析方式,这样 pull 读的就是这份文本所写的资产。它会以四种方式失败:文件声明的是 Module、Emitter 或 DynamicInput 文档而不是 System;根 token 无法解析;解析出的路径上不存在系统;或者 -Asset= 指定的东西不是 Niagara 系统。

修复。 当该资产从未构建过时,先构建文本;或者用 -Asset= 指定你想要的资产。注意 一次导出命名的是哪个资产:plan-v4 会把每个导出写入 Decompiled/ 命名空间,所以一次导出命名的是它的 镜像(MIRROR)—— 拉取别人在原版里调好的值就是 -Asset=/Game/.../NS_X,而且这也是它唯一的 拼写方式,因为一个 Name= 只能指向两者之一。

DFX7109

严重级别 警告

消息

pull: %s: %s. pull rewrites literals inside a structure both sides agree on, so nothing in this stack was addressed.

触发位置 Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:1211、Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:1978、Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:2027、Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:2066、Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:2220、Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:2241

原因。 pull 通过将文本中的语句与资产的节点在同一堆栈中的同一位置进行匹配来定位一个输入,当两者对不齐时 会拒绝整个堆栈:节点数量不同、某一侧是模块调用而另一侧是折叠的赋值序列、某个模块调用的资产并非该节点所运行的 脚本、资产的节点不携带某个 as <name>,或者资产根本没有某个 emitter 或堆栈。

这种拒绝本身就是特性。一个可能偏一位的对应关系会改写错误的字面量,而文本文件中错误的字面量就是静默损坏 —— 因此消息会打印双方的节点名,这同时也是再往后一行就能看到的诊断。

修复。 构建文本,这正是让资产与文本所描述的内容相匹配的操作,然后再 pull。当两者在结构上本就应当不同时 —— 比如一次尚未构建的编辑 —— pull 并不是处理该堆栈内取值的工具。

DFX7110

严重级别 错误

消息

pull: the rewritten text does not read back (%s), so '%s' was left untouched.

触发位置 Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:2411、Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:2545、Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:2553

原因。 写入那一半失败了,而且没有任何东西处于半完成状态。同一段代码覆盖了它可能出现的三种情况: 改写后的文本无法解析(pull 在触碰文件之前会先解析自己的输出,并且只在解析器为该字面量记录的字节范围内进行拼接, 所以这是 pull 的缺陷而非文本的缺陷)、备份无法写入,或者文件本身无法写入。

修复。 当消息表明改写后的文本无法读回时,请上报:磁盘上的文件完全保持原样,pull 所替换的字节范围就是 复现它所需的唯一信息。另外两种是环境问题;当最后一条消息提到某个备份时,文件原本持有的字节就在那里。

DFX7111

严重级别 信息

消息

pull: %s is declared but was not written back: %s

触发位置 Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:1081、Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:1655、Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:1795、Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:1966、Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:1994、Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:2049、Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:2085、Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:2108、Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:2122、Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:2253、Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:2274、Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:2289

原因。 文本声明了该输入,资产也为其存储了值,pull 却仍不会写入它。每一行都指明了具体是哪一个原因:

  • 该值不是字面量 —— 一个链接、一个动态输入、一个 hlsl { } 块、一个 curve { }、一个数据接口或一个 对象引用。改变值的模式(MODE)是一次编辑,而不是一次回写;
  • 文本的值无法通过对该输入的类型检查,构建也会因同样的原因拒绝;
  • 多个输入或多个参数共用一个标识符。DSL 会去掉空格、连字符并忽略大小写,所以值输入 Scale RGB 与对它进行 门控的内联编辑条件 ScaleRGB 对本语言来说就是同一个名字。写入的值究竟指的是哪一个,由其类型决定, 就像生成器所做的那样;pull 只在无法判断时才报告;
  • 同一个参数名被存储在两个脚本中且值不同,因此引擎读取的是哪一份副本并非 pull 所能确定;
  • 存储的值在本语言中没有拼写形式(一个不是 int/float/bool/2-4 个打包浮点数的结构体);
  • 该堆栈是 OnEvent 或 Stage 堆栈,v1 不予处理 —— 那些需要通过聚焦切片读取, 是与这六个固定堆栈不同的机制。

修复。 每一行都指明了它自己的原因,而前两个原因关乎文本而非资产。对于共用标识符,请以不会被解读为另一个的 方式拼写想要的输入,或者改变该值,让它的类型来决定。对于事件堆栈和阶段堆栈,在 v1 中无事可做。

DFX7112

严重级别 信息

消息

pull: %s: %s

触发位置 Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:1614

原因。 -Structure 所应用的每一次结构性编辑各占一行:资产有而文本没有的模块(即被插入的那一行, 逐字原样),或者文本有而资产没有的语句(即被删除的那一行)。

修复。 无。这是本次运行所写下内容的记录,也是被插入的那一行唯一完整出现的地方 —— 摘要只会对编辑计数,否则控制台列表将成为这一行如今已写入文件的唯一副本。

DFX7113

严重级别 警告

消息

pull: %s: the asset has %s that the text does not, and the text has %s that the asset does not. The two lists line up uniquely, so -Structure writes that difference; it adds and removes lines, so it does not happen without the switch. Nothing in this stack was addressed.

触发位置 Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:1302、Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:1606

原因。 文本与资产对某个堆栈结构的描述不同,而 pull 不会写入该差异。有两种形态:

  • 不带 -Structure —— 差异已被定位(节点列表唯一对齐),并且被有意地不应用。 增加或删除一行会改变模块在执行顺序中的位置,而该堆栈内的值是按位置定位的,所以整个堆栈都不动。
  • 带 -Structure —— 差异根本无法写入:某个模块的输入中包含数据接口或对象引用(无法根据存储中的内容 重建该调用)、文本未声明的 Set Parameters 模块(从折叠中拉取一串赋值是另一种编辑)、没有记录字节范围的语句、 与其他内容共用一行的语句,或者解析器没有记录其右花括号的堆栈。

修复。 消息会指明是哪一种。对于第一种,如果需要该编辑,请以 -Structure 重新运行。对于第二种, 先构建文本(dfx build),这会让两种结构一致,并让值回写可用。

DFX7114

严重级别 警告

消息

pull: the baseline could not be used (%s), so every value this text declares was compared from scratch.

触发位置 Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:2442、Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:2448、Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:2484

原因。 脏集合的状态,每次运行只陈述一次而不是猜测:

  • 磁盘上没有基线 —— 该特性到来之后的第一次运行,或者 Saved/DreamFX/Pull/ 下的文件被删除之后。 文本声明的每个值都会被比较,完全与基线存在之前一样,而紧随其后的 -Apply 会记录一个基线。
  • 基线无法使用 —— 不可读,或者某一行不是一条记录。同样会发生完整的比较,只是以警告级别, 因为文件存在却不可用与文件不存在是不同的。
  • 基线无法写入(仅 -Apply)—— 值仍然被写入了;只是缺少了资产原先持有值的记录, 所以下一次运行会再次比较所有内容。

修复。 前两种无需处理:它们描述的是做了保守处理的一次运行。对于第三种,请检查 Saved/DreamFX/Pull/ 是否可写。

DFX7115

严重级别 信息

消息

pull: %s differs from this text but the asset has not moved since the last apply, so the text's value stands.

触发位置: Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:1030

原因. 声明的值与资产的值不同,并且自上次 -Apply 为它记录基线以来资产没有再移动过。这使得 TEXT 成为较新的一方 —— 有人编辑了字面量而不是编辑器 —— 因此文本的值成立,不写入任何内容。这正是脏集的意义所在:没有它,pull 会把资产的读取值置于一个故意与之矛盾的文字编辑之上。

修复. 当文字编辑是有意为之,则无需处理。若要让 pull 仍然写入资产的值,在编辑器中移动该值(基线监视的正是这一点),或删除基线文件以回退到比较所有内容。

DFX7116

严重级别 info

消息

pull: %s: %s -> %s

触发位置: Source/DreamFXEditor/Private/WriteBack/DreamFXPull.cpp:2377

原因. 文本写入的一个字面量与该输入在资产中存储的值不同。该诊断自身的 file(line,col) 是字面量所在的行,消息给出 <module>.<input>、写入的字面量以及它将变成的值。由 dfx pull 为每个字面量触发一次;所比较的值是资产的快速迭代存储,而不是解析后的引脚 —— 这一区别正是 pull 存在的理由(NS_Effects1_Mesh 存储 Sprite_Atlas_Size.MeshYaw = -90,而对引脚的每次读取都返回 0.0)。

修复. 无需处理,除非是你有意为之:没有 -Apply 时运行是试运行,不写入任何字节。dfx pull <file> -Apply 会写入这些值。当某一行出乎意料时,有两件事值得检查:pull 是否读取了你想要的资产(导出会指明其镜像,因此拉取原件的值需要 -Asset=),以及资产是否真的存储了该值 —— 运行报告的是存储自身的内容,而资产从未持有该值的文本没有什么可拉取的。

本页目录