The table below lists a comparison of features and implementation details of Unity plugin frameworks that are considered "modern". As a disclaimer I am a developer of BepInEx which has likely influenced which properties I have compared together.
|Project comparison||BepInEx||IPA||BSIPA||Unity Mod Manager||MelonLoader|
|Code license||LGPL||MIT||MIT||MIT||Apache †|
|Game specific||No||No||Beat Saber||No||No|
|Backwards compatible versioning||Semver||No||Semver||No||No|
|Game engine support||BepInEx||IPA||BSIPA||Unity Mod Manager||MelonLoader|
|Platform support||BepInEx||IPA||BSIPA||Unity Mod Manager||MelonLoader|
|Mac OSX||Native||Partial Wine/Mono||No||Wine/Mono||No|
|Linux||Native + Proton||Partial Wine/Mono||Wine||Wine/Mono||No|
|Feature support||BepInEx||IPA||BSIPA||Unity Mod Manager||MelonLoader|
|External console||Yes||No color||Yes||No||Yes|
|Configuration||Yes (TOML)||No||Yes (JSON)||Yes (XML)||Yes (INI)|
|Plugin logging||Yes||Direct to console||Yes||Yes||Uses stackframes|
|Extensible logging system||Yes||No||Yes||No||No|
|Plugin manifests||Attribute only||No||Yes||Yes||Attribute only|
|Plugin-level dependency sorting||No semver||No||Yes||Yes||No semver|
|Loader version checking||Yes||No||Yes||Yes||No|
|Multi-game directory support||Yes||Yes||No||No||No|
|Preloader assembly swapping||Yes||No||No||No||No|
|Inbuilt manager plugin||No||No||Yes||Yes||No|
|Plugin and loader auto-update||No||No||Yes||Yes||No|
|Manager tool||Unofficially||No||Yes||Yes||Installer only|
|Plugin hot loading||Unofficially||No||Yes||No||No|
|dnSpy debug helpers||Yes||No||No||No||Partial|
|Mechanism||BepInEx||IPA||BSIPA||Unity Mod Manager||MelonLoader|
|Patchless loading||Yes||No||Partial, windows only||Windows only||Windows only|
|Drag + drop installation||Yes||No||Yes||No||Yes|
|Survives updates / integrity checks||Yes||No||Yes||Only updates||Yes|
|Inbuilt Harmony support||2.0 (HarmonyX)||No||2.0||2.0||22.214.171.124|
|Inbuilt MonoMod.RuntimeDetour support||Yes||No||No||No||No|
|Inbuilt IL2CPPAssemblyUnhollower support||Yes||No||No||No||Yes|
|Unity hotfixes||BepInEx||IPA||BSIPA||Unity Mod Manager||MelonLoader|
|Assembly.AppBase + Location unicode fix||Yes||No||No||No||No|
|Unity 2018.X .NET Standard Reflection.Emit fix||Yes||No||Yes||Yes||No|
|Unity 4.x incomplete console implementation fix||Yes||No||Yes||No||Yes|
|Unity <= 5.x incomplete trace implementation fix||Yes||No||No||No||No|
|Terminfo2 support in underlying Mono console driver||Yes||No||Partial||No||No|
|Unix stdout redirection fix||Yes||No||No||No||No|
† MelonLoader does not make it's code history public. Only milestone source releases are available.
Here are some explanations for the above rows:
Pretty straightforward. Has the project receieved an update in the last 12 months?
The license that the source code is under. It restricts what you can do with the code.
The programming language used in the framework, and by extension the language of plugins it supports.
Note that supporting plugins created in a language that executes native code (i.e. C/C++), or a language that is not able to be easily decompiled (also C/C++) is a security risk.
If the loader is mainly intended for a single game and is not easily usable on other games, then it would be difficult to work with.
Does the project have automatic builds for code commits pushed to master?
If the version numbers of the framework indicate that major versions break API/ABI, then the framework has this property.
The most popular form of this versioning system is Semantic Versioning. If a major version number changes (i.e. 1.0.0 -> 2.0.0), then it is not considered backwards compatible. If any number less than that changes (i.e. 1.0.0 -> 1.1.0), then it is still considered backwards compatible.
A matrix of which Unity versions the framework supports. You can determine what version of Unity your game is by right clicking on the game .exe -> Properties -> Details -> Version.
Note that all versions except for IL2CPP are for Mono runtime games.
The operating systems that the framework supports (and in the case of ARM, the type of processor too).
For Linux and Mac OSX, there are four types of support:
BepInEx supports both native execution, and execution through Proton for games that do not have a Linux/OSX version.
Both IPA and UMM support Mono for their installers. However IPA only has partial support without Wine, as it performs Windows system calls without checking what OS it is running under, and can break itself.
BSIPA only supports Wine on Linux. OSX may work too, but is untested.
If the loader can spawn an external console window, then the framework has this property.
Does the loader have a framework for plugin-specific configuration? If so, what configuration file format does it support?
If the framework supports logging per-plugin, then this property is satisifed. Half points if the plugin has to manually identify itself in the log output.
Does the logging system support custom listeners? Can plugins create multiple log sources for their own nefarious uses?
Whether or not the framework supports reading metadata from the plugin itself.
BSIPA and UMM support a complex .json file embedded in the plugin, however BepInEx and MelonLoader only support metadata from code attributes.
Plugins support listing other plugins as dependencies, and the framework will ensure that they are loaded in such an order that all dependencies have already been loaded.
BSIPA and UMM also support adding a version range to this, to ensure that it only loads if the dependencies are also the correct version, and not just the order.
Similar to above, but for ensuring that plugins are only loaded on framework versions that the plugins are compatible with.
Whether or not the loader can execute in directories that contain more than one Unity game, and contains load filters to ensure that plugins are not loaded in games that they are not supposed to load in.
The loader supports executing .DLL edits in-memory. This is different to something like a Harmony hook, as this allows editing the actual .DLL itself.
This is extremely powerful, especially for doing things that Harmony cannot do (for example, adding values to an enum)
Similar to above, but allows switching a .DLL file being loaded with another one.
A built-in plugin that allows the user to perform maintenence tasks, such as enabling and disabling other plugins from loading at launch.
Whether or not the loader has a framework that performs things like auto-updating for both plugins and the launcher itself.
An external tool that handles framework/plugin installation, and plugin enabling/setup.
BepInEx has an unofficial manager tool in Risk of Rain 2.
Plugins can be unloaded and reloaded on demand.
BepInEx only supports this via a developer tool.
Hooks are included that help integration with dnSpy debugging (such as triggering breakpoints).
The loader can execute without needing to patch/edit any files of the game.
BSIPA is considered partial, as while it does not need patching to initially execute, it will patch the game's assemblies for future startups.
The inverse to above, where the game's files are patched to facilitate loading. If this loader supports patchless loading, than patched loading exists as a secondary entrypoint instead of the primary entrypoint.
As it says on the tin. The loader can be installed by simply dragging and dropping the files on top of the install; no additional installation required.
If the framework carries it's own distribution of the Harmony hooking library, and the version it uses.
The framework carries it's own distribution of the MonoMod.RuntimeDetour hooking library.
Fixes a bug where Assembly.AppBase and Assembly.Location will output garbled text if the game is in a folder path that contains unicode characters.
Fixes Harmony hooking on versions of Unity 2018 that break System.Reflection.Emit methods. Note that this is not an issue in MonoMod.RuntimeDetour, and is fixed on Harmony versions 2.0 and above.
Fixes issues with the Console class not supporting things like foreground and background color, and the Title property.
BepInEx and MelonLoader fix this by providing new Console implementations.
Fixes issues with the Trace class calling an incorrect method when reporting a Trace event.
Fixes color terminal support on Linux/OSX/Unix systems.
BSIPA has a partial fix that only works for Terminfo1 TTY terminals.
Fixes stdout logging on Unix platforms, as Unity consumes the data when it shouldn't.