(废墟图书馆)Unity游戏mod通用教程特殊篇:如何优雅地用dnspy调试unity游戏及其mod
天的天空_
2024年04月16日 05:40
收录于文集
共9篇

首先 本篇教程根据dnspy wiki翻译并总结 并经由个人测试以及使用给出具体流程 

代码块
JavaScript
自动换行
复制代码
https://github.com/dnSpy/dnSpy/wiki/Debugging-Unity-Games
复制成功


                    这下就算是死也值回学习dnspy的票价了

在我们mod开发的过程中 你是否想过 有没有什么办法能够实时地监听某个变量的变化 或者实时的能够在游戏中看到errorlog的输出呢

或者 你有没有想过 有什么办法能够去方便的检测线程的变化呢

那么 如果你有一定的c#基础和开发经验 你可能会想到vs的一个系统叫做“调试”

但是 问题又来了 对于废墟图书馆为例子的这种unity游戏 我们如果没有它的原工程文件 该如何调试呢

很简单 我们可以使用Dnspy来进行unity游戏的调试 并且如果你的mod的dll会被该游戏读取

则可以调试改mod

那么 调试又有哪些功能呢?

很多很多....监听变量 测试运行 检查流程 ...总之 想要实现我们在unity游戏mod中更为简便的debugging或是原版游戏流程监听 我们就必须要学会使用调试

根据wiki中的流程 可以把调试办法分为几种游戏的情况下的对应的调试办法

办法一:将unity游戏转为build(debug)架构后 直接使用dnspy的附加到进程(unity)

办法二:将unity游戏的mono文件替换后 使用dnspy的调试并使用unity(mono)调试引擎

在本篇教程中 我们将深入学习办法一的具体流程 而对于办法二 我们将只进行对其流程的翻译以及了解 可以根据自己的需要进行大标题的检索

对于已经完结的游戏 选择办法一 对于仍在更新的游戏 两者均可选择 

但出于办法二国内资源的缺失 其便用程度不一定高于办法一 因此本教程只学习(并推荐)办法一


                 像你这样的dnspy 我们最讨厌喜欢了(办法一)

如果你想了解办法二 可以跳过本大标题

首先 在开启这个大标题前 我们首先需要清楚我们目标游戏的unity版本

如果你的游戏有本地log 那么我们可以在log中找到unity的版本:

如果你的游戏没有本地log 那么我们可以在exe的属性部分找到unity的版本

在确定了unity的版本后 我们需要下载对应版本的unity editor(以获取debug Build架构)

(具体安装教程可参考本系列教程第四篇)

安装完毕后 我们进入如下路径:

在该路径下 我们将使用这两个文件夹中的一个

如果你的游戏是32bit则选择32 64同

然后 (可选)备份你的游戏文件

然后 我们将data文件夹:

复制到游戏名_data的文件中 并覆盖它里面的所有文件

请不要担心 这个复制并不会导致游戏出现问题 它仅仅只是覆盖mono架构 对于承载游戏本身玩法与功能的CSharp dll并无影响与改动 不过出于安全考虑 我仍然建议你(在有内存的情况下) 备份一下游戏

然后 对于老一些的unity版本:

我们需要将这个文件更名为游戏文件夹内游戏exe的名称 然后

覆盖游戏原有的exe

对于新一些的版本(大于2017左右)

我们还需要将这个文件复制(并覆盖)到

游戏的exe文件夹内

然后 

打码的文件夹为非unity通用文件夹

打开这个文件

在其中加入(或修改)该条目为如上

此时 我们进入游戏:

可以 看到 游戏在功能正常的运行外 多了这些内容

首先 最有用的就是左下角的这个development 控制台了

它可以显示unity游戏的所有log 并且如果你点击对应的Log条目 会向你展示它来自的调用堆栈:

这对于我们的日常开发而言 无疑是巨大的帮助

然后 在确保出现了右下角的文字提示后 我们就可以开始dnspy的工作了

首先 打开与你unity游戏bit版本一致的dnspy (32位游戏开32位dnspy 以此类推)

然后 加载我们需要进行调试的dll

然后 按照以下流程进入这个界面:

如果你在这个界面看到了你的目标游戏 那么可以宣告成功 已经可以开始unity游戏的调试了

那么 什么是调试呢?

我们可以参考微软手册的教程:

代码块
JavaScript
自动换行
复制代码
https://learn.microsoft.com/zh-cn/visualstudio/get-started/csharp/tutorial-debugger?view=vs-2022
复制成功

简而言之 就是可以通过添加断点或者进行其它操作 来实时的获取并知晓程序运行时 各个变量与线程(以及内存)的状态 以更加方便的让我们知道 问题出在哪里

在本篇教程中 我们不对c#的调试进行详解 总之dnspy的调试功能与微软手册中的介绍如出一辙

我们进入我们要进行调试的dll 并选择我们要调试的目标方法

对于这个方法而言 就是在游戏废墟图书馆中 处理镜头的方法

我们想要知道游戏处理镜头时 各个参数的状态

因此 我们在方法的一个合适的(确保能够知道目标变量)的位置 添加一个断点:

然后 我们再根据刚才的流程 进入调试界面:

选中要调试的游戏后 我们点击附加:

可以看到 此时dnspy多了一个橙色的运行时 并且我们的断点变成了有详细信息的断点

这是因为 我们调试的这个断点所在的dll 被加载到了我们附加的进程内 因此断点就会开始预备运行

如果此时你的断点是一个黑色的并且右下角带有警示符号的断点 那么说明你当前调试的这个断点在游戏当前的情况下 它处在的方法的dll未被游戏所加载

然后 我们进入游戏 运行游戏到会触发该断点调试目标方法的位置:

可以看到 在我们发动战斗后 游戏突然卡死了 并且dnspy弹到了你的窗口前面

这并不是因为出了什么bug 而是一个激动人心的消息 我们调试成功了

此时的游戏的进程已经被断点终止 在dnspy中我们可以看到如下内容:

在下面的局部变量内 我们可以看到该在当前状态下 所有的变量的详细数值以及内容

是不是非常好用 而且远远不止于此 我们还可以对他们进行修改和监听

不过这里就留作课后作业 交给大家自由去探索了

点击继续后 会取消当前断点的挂起状态 使游戏重新开始运行 直到再一次进入断点

那么这样 我们就学习了如何使用dnspy去调试unity游戏(和mod) 是一个十分十分有用的技巧


                  dnspy是感到寂寞没有mono就会崩溃的程序(办法二)

全文如上 我们对流程来进行一下翻译

首先 我们需要dnspy进行过patch的mono dll(但是只更新至2018版本 此后均需要我们自行进行修改 不光麻烦 而且国内几乎没有对此的教学和mono的资源)

然后 我们需要将dnspy进行过Patch的mono dll覆盖原游戏的dll

然后 我们需要使用调试->开始调试 并且选择unity调试引擎

我们也可以使用unity(connect)来附加到已经开始的游戏上

然后 我们需要根据如上教程提供的环境变量 去进行(可能)的配置

这样 我们就可以对unity游戏进行调试了


                              吔!dnspy 我们敬爱你呀!

总而言之 dnspy是个很强大的工具 还有很多功能是不为国内modder所知的

这里推荐大家去dnspy的wiki官网 进行进一步的了解

顺带(如有可能的话) 可以在本教程的评论区留下你想了解的内容 

欧美得多

求点赞 求关注 求三连