做Unity游戏mod这事,BepInEx算是绕不开的一个名字。无论你是想在存档里给自己塞点装备、给角色换个模型,还是想彻底搞清楚游戏内部到底怎么运作的,BepInEx都能给你一个相对干净、稳定、可控的入口。这篇文章是我从零开始用BepInEx开发Unity游戏mod的完整记录,包括框架选型、环境搭建、第一个插件从编译到运行的整个过程,以及我在实际项目里踩过的几个坑。适合刚接触mod开发的新手,也适合那些已经写过几个小mod、但想系统理解BepInEx工作原理的同学。
1. 选型:Unity modding的几把钥匙,为什么我最终锁定了BepInEx
Unity游戏的mod方式其实不止一条路。官方创意工坊是首选,但不是每个游戏都给你开这个口子,很多单机游戏、独立游戏压根没有官方mod支持。这种情况下,社区里最常见的方案无非三种:BepInEx、MelonLoader,以及绕开框架直接用Harmony手写注入。我个人的经验是,这三种我都试过,BepInEx是目前综合体验最好的选择,但不是唯一选择,选型前需要先搞清楚它们各自的边界。
1.1 主流mod框架横向对比
MelonLoader和BepInEx在功能上有大量重叠,两者都能做到注入游戏进程、加载插件、调用游戏内部方法。但设计理念差异很大。BepInEx定位是“轻量核心+插件生态”,框架本身不掺和太多游戏逻辑,每个插件都是独立的DLL,互不干扰,出问题也好排查。MelonLoader更偏向“开箱即用”,内置了一套Mod偏好设置、Il2Cpp支持和一些常用工具,对新手更友好,但遇到游戏版本更新时,它的维护压力往往更大,兼容性翻车的情况我遇到过不止一次。
再说裸Harmony方案。直接引用0Harmony.dll,手动写补丁、手动组装加载器,这种玩法适合那些想彻底掌控一切的极客。问题在于,一旦游戏里装了多个mod,你就得自己处理程序集加载顺序、依赖冲突、命名空间隔离,这些本来BepInEx已经帮你解决好的问题,裸写全要自己做。我写过一次之后就再也不想了:为了调一个DLL加载顺序,耗时比写核心功能还长。
所以我的结论很简单:如果目标是长期维护、频繁加功能、多个mod共存,闭眼选BepInEx。它不花哨,但稳,社区资料多,遇到问题基本搜得到。
1.2 BepInEx的核心工作方式:从Mono到IL2CPP
要真正理解BepInEx,得先理解Unity游戏的两种脚本后端:Mono和IL2CPP。
Mono时代,游戏的C#代码编译成.NET程序集,直接以DLL文件的形式躺在游戏目录的Managed文件夹里。这种模式的优点是对mod开发者极其友好:你可以直接用dnSpy反编译这些DLL,看到所有类名、方法名、字段名,甚至直接引用它们写代码。缺点是太透明了,游戏厂商没法保护任何逻辑。
IL2CPP是Unity为了性能和代码保护推出的方案。C#代码在发布时会被转换成C++,再编译成原生二进制,游戏目录里不再有可以直接反编译的.NET程序集。很多人以为IL2CPP游戏没法做mod了,但mod社区很早就找到了对策——Il2CppDumper可以从global-metadata.dat文件中提取出类、方法、字段的元数据,虽然不能还原成完整的C#源码,但足够让BepInEx通过Il2Cpp Interop机制生成互操作程序集,让你在mod里像调用Mono程序集一样调用游戏内部方法。
理解这一点后,BepInEx的工作机制就清楚了。它本质上干了三件事:通过doorstop注入器把winhttp.dll注入到游戏进程;在进程内建立插件加载环境,扫描BepInEx/plugins目录加载所有mod插件;通过Harmony补丁系统把mod代码插入到游戏逻辑的执行流程里。这三层玩明白了,后面写mod就是水到渠成的事。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备:一次装对工具链,后面能省十个小时
环境准备是整个过程中最容易被轻视、也最容易出错的一步。很多人下载了BepInEx安装包直接往游戏目录一扔,结果游戏崩了、日志空白、插件不加载,全是因为细节没处理到位。我把一套比较稳的流程拆开讲。
2.1 BepInEx版本怎么选:5系与6系的差别,Mono和IL2CPP怎么判断
BepInEx目前有5系和6系两条主线。5系是老牌稳定版本,分x64和x86两种架构,你要先确认游戏的运行架构,绝大多数Steam游戏都是64位,下载时选x64就对了。6系是当前的主力开发版本,它在架构上做了整合,不再区分Mono和Il2Cpp两个安装包,统一入口,插件API也做了调整,新项目建议直接上6系。
还有一个小原则:如果游戏比较老,比如Unity 2017、2018时代的作品,可能有些老插件只支持BepInEx 5,这时候别固执,老游戏用老框架、新游戏用新框架,是最省力的做法。
怎么判断游戏是Mono还是IL2CPP?一个土办法是看游戏目录:找到GameName_Data文件夹,如果里面有Managed文件夹且包含一堆dll,大概率是Mono;如果看到Native文件夹或者libil2cpp相关文件,那就是IL2CPP。更准确的判断方式:装好BepInEx后启动游戏,看L
