BepInEx:强大的Unity游戏插件框架
项目描述
BepInEx(Bepis Injector Extensible)是一个专业的Unity游戏插件/模组框架,支持Unity Mono、IL2CPP以及.NET框架游戏(包括XNA、FNA、MonoGame等)。该项目提供了完整的插件加载系统、配置管理、日志记录和运行时修补功能,为游戏模组开发者提供稳定可靠的开发环境。
功能特性
🎯 多平台支持
- Unity Mono: Windows、OSX、Linux全面支持
- Unity IL2CPP: Windows和Linux支持
- .NET框架: 兼容XNA、FNA、MonoGame等框架
🔧 核心功能
- 插件自动加载: 自动发现和加载插件程序集
- 配置系统: 强大的配置文件管理,支持数据验证和事件通知
- 日志系统: 多源日志记录,支持控制台、文件和Unity日志输出
- 运行时修补: 基于Harmony的程序集修补功能
- 依赖管理: 完整的插件依赖关系解析
🛠 开发工具
- 插件元数据: 通过属性标记插件信息和依赖关系
- 类型转换器: 支持多种数据类型的序列化和反序列化
- 控制台管理: 跨平台控制台支持,包含颜色和编码处理
- 缓存系统: 程序集缓存加速加载过程
安装指南
系统要求
- Windows 7+ / macOS 10.12+ / Linux (各主要发行版)
- .NET Framework 4.0+ 或 .NET Core 3.1+
- 支持的Unity游戏
安装步骤
-
下载最新版本
# 从GitHub Releases页面下载对应版本 https://github.com/BepInEx/BepInEx/releases -
安装到游戏目录
- 将BepInEx文件解压到游戏根目录
- 确保目录结构如下:
Game/ ├── BepInEx/ │ ├── core/ # 核心库 │ ├── plugins/ # 插件目录 │ └── config/ # 配置文件 ├── doorstop_config.ini └── winhttp.dll # Windows注入器
-
验证安装
- 启动游戏,查看BepInEx控制台输出
- 检查
BepInEx/LogOutput.log文件确认运行状态
使用说明
基础插件开发
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
[BepInPlugin("com.author.pluginname", "My Plugin", "1.0.0")]
[BepInProcess("game.exe")]
public class MyPlugin : BasePlugin
{
internal static ManualLogSource Logger;
private ConfigEntry<bool> ConfigExample;
public override void Load()
{
Logger = Log;
// 配置绑定
ConfigExample = Config.Bind("General", "EnableFeature", true,
"是否启用特定功能");
// Harmony补丁
Harmony.CreateAndPatchAll(typeof(MyPatches));
Logger.LogInfo("插件加载完成!");
}
[HarmonyPatch(typeof(GameManager))]
class MyPatches
{
[HarmonyPostfix, HarmonyPatch("Start")]
static void PostfixStart()
{
Logger.LogInfo("游戏已启动!");
}
}
}
配置系统使用
// 创建配置项
ConfigEntry<int> numberSetting = Config.Bind(
"Section",
"Key",
42,
new ConfigDescription("数值设置示例",
new AcceptableValueRange<int>(0, 100))
);
// 监听配置变化
numberSetting.SettingChanged += (sender, args) =>
{
Logger.LogInfo($"配置已更改: {numberSetting.Value}");
};
日志记录
// 不同级别的日志记录
Log.LogDebug("调试信息");
Log.LogInfo("普通信息");
Log.LogWarning("警告信息");
Log.LogError("错误信息");
Log.LogFatal("严重错误");
核心代码
插件加载系统
/// <summary>
/// 链式加载器核心类,负责插件的发现、加载和初始化
/// </summary>
public abstract class BaseChainloader<TPlugin>
{
protected static readonly string CurrentAssemblyName =
Assembly.GetExecutingAssembly().GetName().Name;
/// <summary>
/// 分析类型定义并转换为插件信息
/// </summary>
public static PluginInfo ToPluginInfo(TypeDefinition type, string assemblyLocation)
{
if (type.IsInterface || type.IsAbstract)
return null;
try
{
if (!type.IsSubtypeOf(typeof(TPlugin)))
return null;
}
catch (AssemblyResolutionException)
{
return null;
}
var metadata = BepInPlugin.FromCecilType(type);
if (metadata == null)
{
Logger.Log(LogLevel.Warning,
$"跳过类型 [{type.FullName}],未指定元数据属性");
return null;
}
if (string.IsNullOrEmpty(metadata.GUID) ||
!allowedGuidRegex.IsMatch(metadata.GUID))
{
Logger.Log(LogLevel.Error,
$"插件GUID无效: {metadata.GUID}");
return null;
}
return new PluginInfo
{
Metadata = metadata,
Location = assemblyLocation,
TypeName = type.FullName
};
}
}
配置管理系统
/// <summary>
/// 配置文件管理类,支持线程安全的配置操作
/// </summary>
public class ConfigFile : IDictionary<ConfigDefinition, ConfigEntryBase>
{
private readonly BepInPlugin _ownerMetadata;
protected Dictionary<ConfigDefinition, ConfigEntryBase> Entries { get; } = new();
/// <summary>
/// 创建新的配置文件
/// </summary>
public ConfigFile(string configPath, bool saveOnInit, BepInPlugin ownerMetadata)
{
_ownerMetadata = ownerMetadata;
ConfigFilePath = Path.GetFullPath(configPath);
if (File.Exists(ConfigFilePath))
Reload();
else if (saveOnInit)
Save();
}
/// <summary>
/// 绑定配置项
/// </summary>
public ConfigEntry<T> Bind<T>(string section, string key, T defaultValue,
ConfigDescription configDescription = null)
{
var definition = new ConfigDefinition(section, key);
var entry = new ConfigEntry<T>(this, definition, defaultValue,
configDescription ?? ConfigDescription.Empty);
Entries[definition] = entry;
return entry;
}
}
路径管理系统
/// <summary>
/// BepInEx使用的路径管理静态类
/// </summary>
public static class Paths
{
/// <summary>
/// BepInEx版本信息
/// </summary>
public static Version BepInExVersion { get; } =
Version.Parse(MetadataHelper.GetAttributes<AssemblyInformationalVersionAttribute>(
typeof(Paths).Assembly)[0].InformationalVersion);
/// <summary>
/// 包含主要托管程序集的Managed文件夹路径
/// </summary>
public static string ManagedPath { get; private set; }
/// <summary>
/// 当前运行的Unity游戏的游戏数据文件夹路径
/// </summary>
public static string GameDataPath { get; private set; }
/// <summary>
/// 核心BepInEx DLL所在的目录
/// </summary>
public static string BepInExAssemblyDirectory { get; private set; }
/// <summary>
/// 主要BepInEx文件夹的路径
/// </summary>
public static string BepInExRootPath { get; private set; }
}
日志系统架构
/// <summary>
/// 手动日志源,提供简单的API来手动发出日志
/// </summary>
public class ManualLogSource : ILogSource
{
private readonly string _sourceName;
public ManualLogSource(string sourceName)
{
_sourceName = sourceName;
}
public string SourceName => _sourceName;
public event EventHandler<LogEventArgs> LogEvent;
/// <summary>
/// 使用指定的日志级别记录消息
/// </summary>
public void Log(LogLevel level, object data) =>
LogEvent?.Invoke(this, new LogEventArgs(data, level, this));
/// <summary>
/// 记录插值字符串消息
/// </summary>
public void Log(LogLevel level,
[InterpolatedStringHandlerArgument("level")]
BepInExLogInterpolatedStringHandler logHandler)
{
if (logHandler.Enabled)
LogEvent?.Invoke(this,
new LogEventArgs(logHandler.ToString(), level, this));
}
}
BepInEx框架通过这些核心组件提供了完整的插件开发解决方案,使得开发者可以专注于业务逻辑而不必担心底层基础设施的实现。