10 分钟完成 BepInEx IL2CPP 插件加载:部署、日志验证与故障定位指南
【免费下载链接】BepInExUnity / XNA game patcher and plugin framework项目地址: https://gitcode.com/GitHub_Trending/be/BepInEx
BepInEx 是面向 Unity 与 XNA 游戏的插件框架。IL2CPP 游戏把 C# 代码编译成了原生二进制,插件生态在这里几乎失效;BepInEx IL2CPP 插件加载的价值在于,它能把GameAssembly与元数据文件还原成可被 .NET 运行时使用的互操作程序集,让反射、Harmony、动态生成这些手段在 IL2CPP 游戏里照常工作。这份指南适合已经决定给 IL2CPP 游戏装插件的人:你会完成部署、看懂doorstop_config.ini里真正起作用的三项配置、用日志确认首次加载成功,并在卡住时按日志信号定位问题。
怎么判断游戏是不是 IL2CPP 环境
这一步决定你该用哪套后端。判断只看游戏根目录下的两个位置:
- 游戏根目录存在
GameAssembly.dll(Windows)或GameAssembly.so(Linux); - 数据目录下存在
il2cpp_data/Metadata/global-metadata.dat。
两个位置的文件都在,就是 IL2CPP 环境,本文内容适用。两个文件都不存在时,大概率是 Unity Mono 后端——Mono 用的 Doorstop 模板与本文不同,入口程序集指向BepInEx\core\BepInEx.Unity.Mono.Preloader.dll,IL2CPP 的排障方法对它不适用。
另外注意平台边界:IL2CPP 后端支持 Windows 与 Linux(经 Wine),不支持 macOS。
最小化部署 BepInEx 需要哪些目录和文件
目标只有一个:让游戏根目录长出一个完整的BepInEx文件夹。有两条途径:
- 下载对应后端的发行压缩包,解压到游戏根目录。
- 从源码编译,需要 .NET 6.0 或更高版本的 SDK:
git clone https://gitcode.com/GitHub_Trending/be/BepInEx cd BepInEx ./build.sh --target CompileWindows 下改用build.cmd --target Compile。这条命令会拉取依赖并编译 Core、Preloader 与各运行时工程,产出的目录结构跟发行包一致。其余构建目标见 docs/BUILDING.md。
无论走哪条路,装完后BepInEx文件夹里core、plugins、config三部分缺一不可,缺任何一块都说明部署不完整。确认齐全后,进入下一步配置核对。
doorstop_config.ini 里哪三项配置决定 IL2CPP 能否接管
游戏目录里应有doorstop_config.ini。对照模板 Runtimes/Unity/Doorstop/doorstop_config_il2cpp.ini,真正要逐字核对的只有三项:
| 配置项 | 模板默认值 | 影响 |
|---|---|---|
[General]的enabled | true | 总开关,为false时游戏进程根本不会加载 BepInEx |
[General]的target_assembly | BepInEx\core\BepInEx.Unity.IL2CPP.dll | 指定启动时加载哪个入口程序集,大小写或斜杠方向写错都会失败 |
[Il2Cpp]的coreclr_path | dotnet\coreclr.dll | CoreCLR 运行时位置,发行包自带 .NET 6 运行时,通常保持默认即可 |
模板里的真实片段:
[General] enabled = true target_assembly = BepInEx\core\BepInEx.Unity.IL2CPP.dll [Il2Cpp] coreclr_path = dotnet\coreclr.dll还有一个隐含约定:入口函数必须是static void Doorstop.Entrypoint.Start(),这条要求直接写在模板注释里,所以目标 DLL 不能换成别的程序集。[Il2Cpp]段里还有一项corlib_dir(默认dotnet),指 CoreCLR 托管核心库所在目录,一般无需改动。
第一次启动后如何在 LogOutput.log 里确认加载成功
启动游戏,打开BepInEx/LogOutput.log,按顺序核对这几个信号:
- ✅ 出现
Running under Unity x.x.x与Runtime version之类的行——说明预加载器已在游戏进程里跑起来; - 每个通过校验的插件各有一行 Loaded 记录;没通过的会有一条
Skipping开头的 Warning,后面跟着原因; BepInEx/interop目录已生成,里面是互操作程序集和assembly-hash.txt。
首次启动会花几分钟生成互操作缓存:Cpp2IL 把GameAssembly反向翻译、Il2CppInterop 据此生成互操作程序集,必要时还会下载对应 Unity 版本的基础库。这段时间进程不动也不闪退,属于正常现象,别中断它。
知道启动顺序后,日志里每段输出对应哪个环节就清楚了:Doorstop 注入 → 预加载器启动 CoreCLR → 生成或复用互操作程序集 → 程序集补丁加载 → 逐个装配插件。日志输出的先后就是执行的先后,卡住时对照这个顺序找断点最快。
按日志信号定位加载失败:空日志、插件数为 0、类型缺失与 Wine 崩溃
排查全部围绕LogOutput.log展开:先翻日志,再判断。
现象:启动即闪退,日志几乎为空
说明 Doorstop 没能接管游戏进程。常见原因是target_assembly路径大小写或斜杠方向写错,也可能是杀软把core里的文件隔离了。做法:
- 把配置里的路径与磁盘实际目录逐字符比对;
- 闪退瞬间盯住控制台,记下红色错误行;
- 重新解压发行包保证文件夹完整;
- 把游戏目录加入杀软白名单,或临时关闭实时防护。
现象:流程完整,但加载的插件数是 0
BepInEx 完整跑完了,结尾却是 0 个插件。在LogOutput.log里搜Skipping,每条被跳过的插件都写明原因。常见的几类:
- 插件元数据不完整:缺
[BepInPlugin]特性、版本无效、名称为空; - GUID 含非法字符——校验正则是
^[a-zA-Z0-9\._\-]+$,只允许字母、数字、.、_、-; - 指向了错误的 BepInEx 大版本,会被直接跳过;
- 依赖的其他插件没加载成功,自身被连带跳过。
修复方式是给插件补齐 GUID、名称、版本三元组,并用与目标大版本匹配的 BepInEx 重新编译插件。
现象:游戏更新后,运行时报类型或成员缺失
BepInEx/interop里的互操作程序集与特定游戏版本绑定,游戏一更新,旧缓存就对不上。确认两点:BepInEx.cfg里IL2CPP.UpdateInteropAssemblies为true(默认值);BepInEx/interop目录的修改时间是否停留在游戏更新之前。
确认过期后,在游戏安装目录里删掉BepInEx/interop整个目录再启动,BepInEx 检测到目录缺失会按当前游戏版本重新生成。注意只操作游戏安装目录下的副本,不要改动源码仓库。离线环境另外处理:把IL2CPP.UnityBaseLibrariesSource改成只写 zip 文件名(不写 URL),并把同名 zip 放进BepInEx下的unity-libs目录,程序会优先使用本地文件而不联网下载。
现象:Wine 下随机崩溃,时机不固定
⚠️ 旧版 Wine 对 CoreCLR 支持不完整,IL2CPP 预加载器(见 Runtimes/Unity/BepInEx.Unity.IL2CPP/Preloader.cs)会主动检测并打 Warning:Your wine version doesn't support CoreCLR properly, expect crashes! Upgrade to wine 7.16 or higher.日志里出现这条时,答案已经写在里面了——把 Wine 升级到 7.16 或更高版本。
现象:首次启动长时间无响应
这是互操作生成在跑,可能还包含 Unity 基础库下载。日志里应有 interop 相关进度输出;确认UnityBaseLibrariesSource指向的地址可达,然后等它跑完。离线环境按上一小节的方式提供本地 zip。
想继续深入时看哪些模块和文档
- 加载顺序与依赖解析:BepInEx.Core/Bootstrap/BaseChainloader.cs,重点是 GUID 校验与大版本比对逻辑;
- 互操作程序集何时加载:Runtimes/Unity/BepInEx.Unity.IL2CPP/IL2CPPChainloader.cs;
- 互操作缓存路径、基础库来源、元数据文件位置:集中在 Il2CppInteropManager.cs 顶部的配置绑定,改行为前先读那里的注释;
- 插件元数据与依赖特性定义:BepInEx.Core/Contract/Attributes.cs;IL2CPP 下新增自定义 MonoBehaviour 要走类型注册(见
Runtimes/Unity/BepInEx.Unity.IL2CPP/Utils/Il2CppUtils.cs),不能照搬 Mono 写法——这是两个后端最大的开发差异; - 构建参数全集:docs/BUILDING.md,构建脚本需要 .NET 6.0 或更高版本 SDK。
遇到疑难问题时,先把LogOutput.log里的版本号行、各插件 Loaded 行、Skipping警告原文整理出来——日志本身就是定位问题的第一手证据。
【免费下载链接】BepInExUnity / XNA game patcher and plugin framework项目地址: https://gitcode.com/GitHub_Trending/be/BepInEx
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考