前言
相关内容来自RimWorld Wiki ,本文仅做翻译和有限的补充,除非另有说明,所属内容均在 CC BY-SA 3.0 下提供。
RimWorld Wiki:https://www.rimworldwiki.com/wiki/Main_PageRimWorld
RimWorld Wiki - Troubleshooting:https://www.rimworldwiki.com/wiki/Modding_Tutorials/Troubleshooting
水平有限,如有错漏,敬请见谅
如果您喜欢这篇文章,麻烦大家帮我点个赞,谢谢大家的支持!
常见的XML错误
语法错误
对于初学者来说,最常见的错误是格式和语法错误。如缺少括号、未闭合的标签、空文件等,这些都可以通过使用适当的工具来避免。
通过一个合适的文本编辑器(或插件)可以突出显示、警告这些基本问题。RimWorld不会因这些问题警告你,最好的情况下游戏会带着错误运行,最坏的情况下游戏会直接拒绝启动。
大小写错误和意外空格同样是语法错误。compClass
和 CompClass
是两个不同的东西。空格同样邪恶,<compClass>MyNamespace.MyClass </compClass>
会让你永远摸不着头脑,为什么RimWorld找不到 MyNamespace.MyClass
。
看不出 <compClass>MyNamespace.MyClass </compClass>
有什么错误?
现在呢 <compClass>MyNamespace.MyClass[空格]</compClass>
?
交叉引用 Cross-references
关键词(译者附):Could not resolve cross-reference
1、 def A 想要使用 def B,但是找不到 def B。这些交叉引用是通过 defName 进行的。Type 和 defName必须匹配。如下例:
Could not resolve cross-reference: No SoundDef named Slurp found to give to ThingDef ExampleThing.
这表示名为 ExampleThing 的 ThingDef 试图使用名为 Slurp 的 SoundDef ,但游戏找不到名为 Slurp 的 SoundDef 。
这种交叉引用一般长这样(译者附):
<ThingDef>
<defName>ExampleThing</defName>
<!-- 其他标签 -->
<requireSoundDef>Slurp<requireSoundDef> <!-- 标签名无所谓,主要在于该标签接受的值是SoundDef 类型的 -->
<!-- 其他标签 -->
</ThingDef>
2、如果游戏在列表中找不到交叉引用,则错误略有不同:
Could not resolve cross-reference to Verse.ThingCategoryDef named BuldingsPower (wanter=thingCategories)
这表示 thingCategories 试图获取名为 BuldingsPower 的 ThingCategoryDef ,但失败了。其中wanter=thingCategories
是可选显示的附加项。
这种交叉引用一般长这样(译者附):
<ThingDef>
<defName>ExampleThing</defName>
<!-- 其他标签 -->
<!-- 注意<thingCategories>标签是一个【列表】标签 -->
<thingCategories> <!-- 这个标签就是wanter -->
<li>BuldingsPower</li>
</thingCategories>
<!-- 其他标签 -->
</ThingDef>
定义同一字段/标签两次 Defining the same field/tag twice
关键词(译者附):defines the same field twice
XML RimWorld.ThoughtDef defines the same field twice: stackLimit.
Field contents: 1.
Whole XML: < 一堆XML标签 >
上例表示,有一个 ThoughtDef 却错误的包含两个 stackLimit 标签的。这可能是错误的在XML文件中定义了两次标签,也有可能是两个模组对相同 Def 的进行补丁操作后果,此时第一个模组优先。后一种情况是一种典型的模组冲突,缺乏防御补丁。另请参见防御补丁。
你可以从Whole XML: < 一堆XML标签 >
定位到出现错误的XML标签的名称。
缺少类型 Missing a Type
关键词(译者附):Could not find type
Could not find type named TurretExtensions.CompProperties_Upgradable from node < 一堆XML标签 >
XML引用未加载的类型时,就会发生这种情况。在实践中,一般发生在缺少(DLL)依赖项、由于早期错误而无法加载(DLL)依赖项以及使用了过时模组等情况下。
你可以从Whole XML: < 一堆XML标签 >
定位到出现错误的XML标签的名称。
引用不存在的字段 Referencing a non-existing field
关键词(译者附):doesn't correspond to any field in
当在日志中看到这样的错误信息:
XML error: <costStaffCount>50</costStaffCount> doesn't correspond to any field in type ThingDef. Context: <ThingDef ParentName="SculptureBase"><defName>SculptureSmall</defName><label>small sculpture</label> <description>An artistic sculpture.</description><stuffCategories><li>Metallic</li><li>Woody</li><li>Stony</li></stuffCategories><costStaffCount>50</costStaffCount></ThingDef>
略微整理一下:
XML error: <costStaffCount>50</costStaffCount> doesn't correspond to any field in type ThingDef. Context:
<ThingDef ParentName="SculptureBase">
<defName>SculptureSmall</defName>
<label>small sculpture</label>
<description>An artistic sculpture.</description>
<stuffCategories>
<li>Metallic</li>
<li>Woody</li>
<li>Stony</li></stuffCategories>
<costStaffCount>50</costStaffCount>
</ThingDef>
这表示在名为 SculptureSmall 的 ThingDef 中使用了<costStaffCount>
标签,但 ThingDef 中根本不存在<costStaffCount>
标签。
这可能是由简单的拼写错误、将标签放在错误的节点、缺少(DLL)依赖项、由于早期错误而无法加载(DLL)依赖项以及使用了过时模组等情况引起的。
注意:XML标签只能对应于 C# 中定义的字段。
关于(解决)XML错误的注意事项
XML错误是级联的。
在后台,RimWorld将所有 def 组合到一个庞大的XML文档中。如果一个标签<tag>
缺少其对应结束标签</tag>
,那么解析器将无法读取任何XML,你将看到一大堆红色错误。
不要恐慌,先找到第一个XML错误,并修复它。不要去管后面的其它错误。重新加载游戏,然后再修复下一个错误(如果有的话)。
堆栈跟踪
通常所谓的 模组冲突/不兼容/加载顺序问题 归根结底只是一个Bug。就像80%的统计数据都是当场生成的一样,RimWorld中98%的报告错误都是 NullReferenceExceptions(空引用异常)。这些被遗忘的null检查可能很难被定位,但一旦定位成功,一般很容易解决。
从上到下阅读堆栈跟踪,首先是错误,然后是导致错误的所有方法。让我们看看下面的堆栈跟踪:
Exception in BreadthFirstTraverse: System.NullReferenceException: Object reference not set to an instance of an object
at Gloomylynx.TantrumPatch.CheckForDisturbedSleepPrefix (Verse.Pawn) <0x00021>
at (wrapper dynamic-method) Verse.Pawn.CheckForDisturbedSleep_Patch1 (object,Verse.Pawn) <0x00020>
at Verse.Pawn.HearClamor (Verse.Thing,Verse.ClamorDef) <0x000b4>
at Verse.GenClamor/<DoClamor>c__AnonStorey0.<>m__0 (Verse.Region) <0x001b0>
at Verse.RegionTraverser/BFSWorker.BreadthFirstTraverseWork (Verse.Region,Verse.RegionEntryPredicate,Verse.RegionProcessor,int,Verse.RegionType) <0x000f7>
at Verse.RegionTraverser.BreadthFirstTraverse (Verse.Region,Verse.RegionEntryPredicate,Verse.RegionProcessor,int,Verse.RegionType) <0x00130>
Exception in BreadthFirstTraverse
:捕获错误的位置:那里有一个try/catch
块,并且捕获了这个错误;System.NullReferenceException: Object reference not set to an instance of an object
:错误类型。NullReferenceExceptions 是最常见的错误类型。它表示“没有为引用对象设置实例”,这意味着某些内容没有初始化(= 实例化);- 堆栈跟踪的底部通常不太有趣,大多数有用的东西都是从 ~3 次调用开始的。在本例中,
Verse.GenClamor
调用了Pawn.HearClamor
,后者调用了Pawn.CheckForDisturbedSleep
,后者调用了Gloomylynx.TantrumPatch.CheckForDisturbedSleepPrefix
,最终导致了错误; at (wrapper dynamic-method) Verse.Pawn.CheckForDisturbedSleep_Patch1 (object,Verse.Pawn)
这是使用了 Harmony Patch 的证据。HugsLib 提供了所有Harmony Patch 方法的列表,这通常有助于查看某个模组做了什么。如果你发现了一个错误,但没有相关模组的提示,该列表会很有帮助。- 如果堆栈跟踪中有多个 Harmony Patch 方法,则可能存在模组冲突。不过大多数时候还是因为抛出错误的模组没有考虑某些内容可能是空(null)的。顾名思义,Harmony (和谐)的美妙之处在于多个模组可以毫无问题地修补相同的方法。
提交错误报告
使用穷举模组组合的方式来测试模组是完全不可能的。有些模组有数千行代码,因此 x breaks 并不能帮助任何人解决问题。模组制作者可以尽最大努力进行游戏测试,但某些模组配置很可能是制作者独有的。如果玩家在模组游玩过程中遇到问题,请务必通知模组制作者。命令模组制作者修复问题是糟糕的行动(毕竟模组制作者都只是“志愿者”),但大多数模组制作者都希望他们的模组没有问题。
日志(Logs),特别是由HugsLib提供的日志,在定位问题的位置方面具有巨大的价值。解决问题的第一步是告知模组制作者你遇到的问题并向他们提供日志和重现步骤。
译者附:问题描述(必须) + 日志(必须) + 重现步骤(如果可以)
请参阅本指南,了解如何以最佳方式提交错误报告。
日志的使用(译者补充)
日志(Logs,Debug log),在RimWorld中将其称为“调试窗口”,会在发生错误时主动跳出,也可以手动打开。
有时候,日志报了错但手滑关掉了怎么办?日志是可以主动打开的,方法如下:
- 进入游戏,在主界面找到“选项” 或者 游戏过程中在右下角菜单找到“选项” ;
- 进入选项,打开“开发者模式”
- 这时游戏屏幕最上方会出现一小排按钮,在主菜单和游戏中均可见,最左边就是日志,鼠标悬停在上方时会显示“打开调试窗口”:
主界面:
游戏中:
- 单击即可打开日志:
原版日志(调试窗口)的使用方法
解释一下日志顶部按钮的用处,虽然鼠标悬停就有对应说明。
- 清除:清除所有日志。会清空调试窗口中的所有内容;
- 大、中等、小窗口:设置堆栈跟踪窗口的大小。注意是堆栈跟踪窗口,而非调试窗口。效果如下:
大窗口:
中等窗口:
小窗口:
- 自动开启:调试窗口是否会在发生错误时自动打开,默认是开启状态。如果有你在游玩过程没有大问题,但存在一些无伤大雅的错误,调试窗口会不断打开提醒你有错误,这时候可以将自动开启设为关闭,仅当次游玩有效。游戏关闭后再启动自动开启会主动变为开启状态;
- 复制到剪切板:复制所有信息到剪切板。一般不推荐这么做,所有信息包含了大量和真正问题无关的信息。推荐做法如下:
- 单击你需要解决的红色错误或黄色提醒,这时注意到堆栈跟踪窗口发生改变,复制堆栈跟踪窗口的内容(鼠标拖选后使用Ctrl+C进行复制)
- 单击你需要解决的红色错误或黄色提醒,这时注意到堆栈跟踪窗口发生改变,复制堆栈跟踪窗口的内容(鼠标拖选后使用Ctrl+C进行复制)
安装Hugslog模组之后的变化
安装Hugslog模组之后在原版日志窗口的堆栈跟踪窗口上添加了三个按钮:
- 导出日志:会将你的日志上传到公共服务器,以方便问题的解决。可以使用Ctrl+F12在不打开开发者模式的情况下使用。在正式上传前会弹出提示窗口:
- 文件:单击会打开下拉菜单,可以方便的进入日志、存档和Mod文件夹;
- 复制:单击即可复制当前堆栈跟踪窗口的内容。