Skip to content

Latest commit

 

History

History
163 lines (113 loc) · 5.15 KB

File metadata and controls

163 lines (113 loc) · 5.15 KB
testedGameBuild 740622
targetFramework netstandard2.1
apiVersion 2
lastVerified 2026-07-15

::: info 验证环境 本页内容已按 Build 740622 对应的本机 Managed DLL 和项目配置检查;尚未在游戏内完成运行验证。 :::

Mod 开发路线

先跑通一个小补丁,再一次加入建筑、配方和本地化。每个示例都是独立项目,不需要合并成一个大工程。

编译 → 加载 → 注册内容 → 游戏内测试 → 打包

1. 编译项目

游戏 DLL 不提交到仓库。编译时把 GameManagedDir 指向本机的 Managed 目录:

$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/Directory.Build.props,项目文件里不写死 Steam 路径。

2. 先做一个最小补丁

examples/FirstMod/ 会把原版电解器的功耗改成 1W。入口代码如下:

<<< @/examples/FirstMod/Mod.cs{csharp}

这里用 Postfix 修改原方法的返回对象:

  • 改初始化结果:优先考虑 Postfix
  • 改输入或阻止原方法:再考虑 Prefix
  • 记录异常或清理资源:使用 Finalizer
  • 只有普通补丁无法表达需求时,才使用 Transpiler

编译后把 examples/FirstMod/bin/ 的内容复制到:

%USERPROFILE%\Documents\Klei\OxygenNotIncluded\mods\Dev\ONITutorial.FirstMod\

启动游戏,启用 Mod,打开测试存档确认功耗变化。日志位置:

%USERPROFILE%\AppData\LocalLow\Klei\Oxygen Not Included\Player.log

3. 开始添加游戏内容

目标 主要入口 示例或章节
新建筑 IBuildingConfigRegisterBuilding 新增建筑examples/Building/
新配方 ComplexRecipefabricators 配方系统examples/Recipe/
新文本 STRINGS.po 本地化examples/Localization/
接入已有科技 Db.InitializeunlockedItemIDs 科技树examples/ResearchExistingTech/

新建筑的顺序

  1. CreateBuildingDef() 定义尺寸、材料和基础属性。
  2. ConfigureBuildingTemplate() 添加 StorageOperationalEnergyConsumer 等组件。
  3. GeneratedBuildings.LoadGeneratedBuildings 中注册建筑。
  4. ModUtil.AddBuildingToPlanScreen 加入建造菜单。
  5. Db.Initialize 中加入已有科技。

完整配置看 examples/Building/BuildingConfig.cs,入口看 examples/Building/Mod.cs。先使用原版动画验证流程,功能正常后再加入自己的动画资源。

配方和本地化

配方通过 fabricators 绑定工艺台。Tag 必须和目标建筑的 PrefabTag 一致,完整代码见 examples/Recipe/Mod.cs

本地化固定走这条流程:

RegisterForTranslation → CreateLocStringKeys → 加载 translations/<locale>.po

完整代码见 examples/Localization/Mod.cs.po 文件必须出现在最终 Mod 目录的 translations/ 下。

科技解锁

先加入已有科技,不要一开始创建新科技节点:

Tech tech = Db.Get().Techs.TryGet("BasicRefinement");
if (tech != null && !tech.unlockedItemIDs.Contains(contentId))
    tech.unlockedItemIDs.Add(contentId);

contentId 必须是已经注册的建筑或物品 ID。只修改科技列表,不会自动生成游戏内容。

4. 一次性检查示例

有本机游戏 DLL 后运行:

./scripts/verify-examples.ps1 `
  -GameManagedDir $managed

脚本会逐个编译示例,并检查 DLL 引用和 mod_info.yaml 的现代写法。

5. 打包

最终 Mod 目录至少应该有:

YourMod/
├── YourMod.dll
├── mod.yaml
├── mod_info.yaml
├── translations/    # 有翻译时才需要
└── anim/            # 有动画时才需要

mod.yaml 只写展示信息:

title: "Your Mod"
description: "A short description."
staticID: "AuthorName.YourMod"

现代 DLL Mod 的 mod_info.yaml

minimumSupportedBuild: 740622
version: 1.0.0
APIVersion: 2

minimumSupportedBuild 换成实际测试过的 Build。没有 DLC 限制时不要添加 DLC 字段;有依赖时使用 requiredDlcIds

详细规则见 Mod 打包与发布多版本兼容性

6. 出错时先查这几项

现象 检查位置
编译失败 GameManagedDir 和游戏 DLL 是否匹配
Mod 不显示 DLL、mod_info.yaml 是否在同一目录
补丁没效果 目标方法、补丁时机、是否复制了新 DLL
建筑不出现 RegisterBuilding、建造分类、科技 ID
配方不显示 fabricators Tag 和 PrefabTag
文本显示 ID STRINGS key 和 translations 目录

开发时不要同时启用同一个 Mod 的 Steam、Local 和 Dev 版本,否则很难判断实际加载的是哪一份。