堆栈跟踪
通常所谓的 模组冲突/不兼容/加载顺序问题 归根结底只是一个Bug。就像80%的统计数据都是当场生成的一样,RimWorld中98%的报告错误都是 NullReferenceExceptions(空引用异常)。这些被遗忘的null检查可能很难被定位,但一旦定位成功,一般很容易解决。
从上到下阅读堆栈跟踪,首先是错误,然后是导致错误的所有方法。让我们看看下面的堆栈跟踪:
Exception in BreadthFirstTraverse: System.NullReferenceException: Object reference not set to an instance of an objectat 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 (和谐)的美妙之处在于多个模组可以毫无问题地修补相同的方法。