验证环境
本页内容已按 Build 740622 对应的本机 Managed DLL 和项目配置检查;尚未在游戏内完成运行验证。
游戏源码分析工具
想真正理解《缺氧》的行为逻辑,光看教程不够,还是得回到游戏源码本身。 这一步通常会从反编译 Assembly-CSharp.dll 开始,因为大多数建筑、实体、AI、UI 和系统逻辑都藏在这里。
这一章主要讲两件事:
- 你该用什么工具来看源码
- 你该怎么从源码里提取出可用于 Harmony Patch 的信息
一、先认识目标文件
《缺氧》的主要逻辑程序集通常位于:
OxygenNotIncluded_Data/Managed/Assembly-CSharp.dll你在 dnSpy 里最常看的,也基本就是这个文件。 如果你想研究某个系统是否有别的依赖,通常还会顺手看这些程序集:
Assembly-CSharp-firstpass.dll0Harmony.dllUnityEngine.dllUnityEngine.CoreModule.dll
但真正决定游戏行为的大部分入口,还是 Assembly-CSharp.dll。
二、为什么选 dnSpy
dnSpy 是《缺氧》Mod 圈里最常用的反编译工具之一,因为它同时能做三件事:
- 查看 C# 反编译结果
- 搜索类名、方法名、字符串
- 直接导出项目或做基础修改
对于 ONI 来说,它最实用的地方不是“能改源码”,而是“能帮你快速找到 Patch 点”。
适合做什么
- 找某个建筑配置类,比如
ElectrolyzerConfig - 找某个方法名,比如
CreateBuildingDef - 看某个方法到底调用了什么
- 判断一个逻辑是在
Prefix、Postfix还是Transpiler更适合处理
不适合把它当成什么
- 不是完整的项目管理工具
- 不是 IDE
- 不是 Mod 编译环境
它更像一个“源码放大镜”。
三、安装和打开
1. 下载
- 官方仓库:dnSpyEx Releases
建议直接下载 Release 版本,不需要自己编译。
2. 打开游戏程序集
- 进入游戏目录
- 找到
OxygenNotIncluded_Data/Managed/Assembly-CSharp.dll - 把它拖进 dnSpy,或者用
File->Open
打开后,你会看到左侧是一棵程序集树,里面展开的就是命名空间、类、方法和字段。
四、怎么在 dnSpy 里找东西
1. 按类名找
如果你已经知道目标类的名字,这是最快的方式。
例如:
ElectrolyzerConfigGeneratedBuildingsDbBuildingDef
可以直接搜索类名,然后展开看内部方法。
2. 按方法名找
如果你只知道行为,不知道类名,可以直接搜方法名。
例如:
CreateBuildingDefOnSpawnConfigureBuildingTemplateLoadGeneratedBuildings
这类方法经常就是 Mod 的入口。
3. 按字符串找
如果你记得游戏里出现过某句文本,也可以用字符串倒推代码。
例如:
- 某个建筑名称
- 某个日志文本
- 某个错误提示
这种方式有时候比类名搜索更快,因为你会先找到“被调用的地方”,再回头找类和方法。
4. 按调用关系找
如果你已经找到一个方法,想知道它是从哪儿被调用的,可以看:
ReferencesAnalyze- 调用链
这对理解“这个函数什么时候跑”的帮助很大。
五、怎么看 ONI 的源码
ONI 的代码读法,和普通 C# 项目有点像,但也有自己的习惯。
1. 先看类名
类名通常会告诉你这个东西是什么。
例如:
ElectrolyzerConfig通常是电解器配置BuildingDef通常是建筑定义GeneratedBuildings常和建筑注册有关
如果类名看起来像 Config、Def、Manager、StateMachine,通常都值得多看一眼。
2. 再看方法名
方法名通常比类名更关键,因为真正的逻辑往往藏在方法里。
在 ONI 里很常见的几类方法有:
CreateBuildingDefConfigureBuildingTemplateOnSpawnOnPrefabInitLoadGeneratedBuildings
这些方法里,前两个通常和“定义”有关,后两个通常和“实例行为”有关。
3. 最后看参数和返回值
参数和返回值能帮你判断这个方法是:
- 只是设置数据
- 还是会改状态
- 还是会返回一个新对象
例如:
void:很多时候是初始化、注册、附加逻辑bool:常用于是否允许执行BuildingDef:通常是构造或修改建筑定义GameObject:通常和预制体、实体生成有关
六、从源码里提取 Patch 信息
这是 dnSpy 对 ONI Mod 开发最有价值的部分。
你最终想提取出来的,一般是这三样:
- 类名
- 方法名
- 参数类型
例子 1:普通方法
源码大概长这样:
public static void LoadGeneratedBuildings()可提取的 Patch 信息:
[HarmonyPatch(typeof(GeneratedBuildings), "LoadGeneratedBuildings")]例子 2:带参数的方法
源码大概长这样:
public void SetActive(bool value)如果你只写方法名,遇到重载时就可能出问题。 这时候就要把参数类型也带上。
例子 3:属性
如果你看到的是属性,不是普通方法,要注意 Getter / Setter。
例如:
public bool IsSolid { get; }这种情况就不是简单搜方法名了,而是按属性处理。
七、一个典型的读源码流程
你可以按这个顺序来:
- 在游戏里确认你想改的对象
- 在 dnSpy 里找这个对象对应的类
- 找
Create...、OnSpawn、Configure...之类的方法 - 看方法内部调用了哪些东西
- 找出最适合下手的位置
- 再回到 Harmony 里写 Patch
如果你只是为了“改个数值”,很多时候不用深挖整个类。 但如果你要改流程、改条件判断、改调用顺序,就一定要把上下文看完整。
八、常见坑
1. 只看到了表面代码
dnSpy 反编译出来的是可读 C#,但不等于原始源码。 有些结构是反编译器“尽量还原”的,真正逻辑要结合调用关系一起看。
2. 忽略重载
同名方法很多时候不止一个。 如果不看参数类型,你很容易 Patch 错目标。
3. 把静态方法和实例方法混了
静态方法和实例方法在 Patch 写法上有时会有差别,尤其是参数和上下文读取方式。
4. 只看一次就急着写补丁
最好先看三层:
- 这个方法做什么
- 它被谁调用
- 它的返回值会不会影响后续逻辑
这样写出来的 Patch 会稳很多。
九、和 Harmony 的配合方式
dnSpy 的任务,是帮你把 Patch 目标找准。 Harmony 的任务,是帮你把修改干净地挂上去。
一般来说:
- dnSpy 用来确认类、方法、参数
- Harmony 用来执行 Prefix / Postfix / Transpiler
如果你已经在 C# 基础 里熟悉了 namespace、class、ref 这些概念,再结合这里的源码分析,你就能比较顺地从“看懂”走到“改动”。
十、下一步
如果你已经会打开程序集、搜索类名、找到方法入口了,下一步就可以去看:
这两篇会把你从“找到源码”带到“真正开始写补丁”。