验证环境
本页内容已按 Build 740622 对应的本机 Managed DLL 和项目配置检查;尚未在游戏内完成运行验证。
第一个 Mod
先做一个最小改动:把原版电解器的工作功耗改成 1 W。这个例子不新增建筑、不改存档,适合确认编译、加载和 Harmony 补丁都正常。
项目结构
仓库里已经有完整示例:
examples/FirstMod/
├── FirstMod.csproj
├── Mod.cs
├── STRINGS.cs
├── mod.yaml
└── mod_info.yaml所有示例共用 examples/Directory.Build.props。它从 GameManagedDir 读取游戏 DLL,不依赖固定 Steam 路径。
两个 YAML 文件不要混用:
mod.yaml 放显示信息:
title: "ONI Tutorial First Mod"
description: "The smallest compilable ONI Mod example."
staticID: "ONITutorial.FirstMod"mod_info.yaml 放加载和版本信息:
minimumSupportedBuild: 740622
version: 1.0.0
APIVersion: 2740622 是当前示例的测试 Build。换版本测试后,改成实际验证过的数字。没有 DLC 限制时,不要添加 DLC 字段。
入口和补丁
Mod 入口继承 UserMod2。完整代码在 examples/FirstMod/Mod.cs:
using HarmonyLib;
using KMod;
using UnityEngine;
namespace ONITutorial.FirstMod
{
public sealed class Mod : UserMod2
{
public override void OnLoad(Harmony harmony)
{
base.OnLoad(harmony);
Debug.Log("[ONITutorial.FirstMod] Loaded");
}
[HarmonyPatch(typeof(ElectrolyzerConfig), nameof(ElectrolyzerConfig.CreateBuildingDef))]
private static class ElectrolyzerPatch
{
private static void Postfix(ref BuildingDef __result)
{
if (__result != null)
__result.EnergyConsumptionWhenActive = 1f;
}
}
}
}补丁打在 ElectrolyzerConfig.CreateBuildingDef,因为电解器功耗是在创建 BuildingDef 时设置的。原版方法先完成,Postfix 再修改返回值:
[HarmonyPatch(typeof(ElectrolyzerConfig), nameof(ElectrolyzerConfig.CreateBuildingDef))]
private static class ElectrolyzerPatch
{
private static void Postfix(ref BuildingDef __result)
{
if (__result != null)
__result.EnergyConsumptionWhenActive = 1f;
}
}选择补丁时记住三点:
- 修改返回对象:通常用
Postfix。 - 修改参数或阻止原方法:考虑
Prefix。 - 记录异常和清理:使用
Finalizer。
只有普通 Prefix/Postfix 无法完成需求时,才使用 Transpiler。
编译
在仓库根目录执行:
$managed = "D:\SteamLibrary\steamapps\common\Oxygen Not Included\OxygenNotIncluded_Data\Managed"
dotnet build .\examples\FirstMod\FirstMod.csproj `
--configuration Debug `
-p:GameManagedDir=$managed把路径换成自己的游戏安装目录。也可以先设置环境变量:
$env:ONI_GAME_MANAGED_DIR = $managed编译成功后,输出在:
examples/FirstMod/bin/复制到游戏
开发时使用 mods/Dev:
$modDir = "$env:USERPROFILE\Documents\Klei\OxygenNotIncluded\mods\Dev\ONITutorial.FirstMod"
New-Item -ItemType Directory -Force $modDir | Out-Null
Copy-Item .\examples\FirstMod\bin\* $modDir -Recurse -Force不要只复制 DLL。mod.yaml 和 mod_info.yaml 也要在同一个目录。
同一个 Mod 不要同时打开 Steam、Local 和 Dev 版本,否则很难判断游戏加载的是哪一份。
游戏内验证
- 启动游戏并启用
ONI Tutorial First Mod。 - 打开测试存档,找到电解器。
- 确认工作功耗变为
1 W。 - 如果没有变化,查看日志:
%USERPROFILE%\AppData\LocalLow\Klei\Oxygen Not Included\Player.log搜索 ONITutorial.FirstMod、Harmony 和 Exception。
编译成功只说明代码能生成 DLL,不代表游戏一定加载了正确目录。每次修改都按“编译 → 复制 → 启动 → 验证”的顺序测试。
常见问题
| 现象 | 先检查 |
|---|---|
找不到 KMod 或 BuildingDef | GameManagedDir 是否指向 Managed |
| Mod 列表里没有项目 | DLL、两个 YAML 是否在同一目录 |
| 有加载日志但功耗没变 | 方法名、补丁签名和复制的 DLL |
| 修改后仍是旧结果 | 是否启用了另一份 Steam/Local/Dev Mod |
| 启动时报类型或方法异常 | 游戏 Build 和编译时 DLL 是否一致 |