This is a BepInEx 5 plugin that allows you to run C# script files without compiling them to a DLL.
This plugin uses a modified version of the Mono Compiler Service (mcs) that allows to use most of C# 7 features.
The compiler relies on System.Reflection.Emit
being present! As such, Unity games using .NET Standard API (i.e. has netstandard.dll
in the Managed
folder)
will not be able to run this plugin!
Now scripts ignore visibility checks! Thanks to custom MCS, you can now access private members (methods, fields) via scripts!
Because sometimes I'm lazy to open Visual Studio and write proper plugins.
Download the latest plugin version from releases and place it into BepInEx/plugin
folder.
To install scripts, create a scripts
folder in the game's root folder and place raw .cs
files (C# source code) into it.
To remove scripts, remove them from the scripts
folder (or change file extension to .cs.off
).
ScriptLoader will automatically load and compile all C# source code files it finds in the folder.
ScriptLoader will also automatically run any static void Main()
methods it finds.
Example script:
using UnityEngine;
public static class MyScript {
public static void Main() {
Debug.Log("Hello, world!");
}
public static void Unload() {
// Unload and unpatch everything before reloading the script
}
}
ScriptLoader automatically detects changes in the scripts and reloads them.
In order to make your script reloadable, you must implement static void Unload()
method that cleans up any used resources.
This is done because of Mono's limitation: you cannot actually unload any already loaded assemblies in Mono. Because of that, you should
clean up your script so that the newly compiled script will not interfere with your game!
You can specify metadata at the very start of your script by using the following format:
// #name Short name of the script
// #author ghorsington
// #desc A longer description of the script. This still should be a one-liner.
// #ref ${Managed}/UnityEngine.UI.dll
// #ref ${BepInExRoot}/core/MyDependency.dll
// #proc_filter Game.exe
using UnityEngine;
...
The proc_filter
tag acts like BepinProcess attribute in BepInEx: it allows you to specify which processes to run the script on.
The ref
tag is special: ScriptLoader will automatically load any assemblies specified with the tag.
The path is relative to the scripts
folder, but you can use ${Folder}
to reference some special folders.
Currently the following special folders are available:
Managed
-- path to the game's Managed folder with all the main DLLsScripts
-- path to thescripts
folderBepInExRoot
-- path to theBepInEx
folder
WIP: At the moment, all tags but ref
have no effect. A GUI is planned to allow to disable any scripts.
At this moment the compilation errors are simply written to the BepInEx console.
Starting 1.2.4.0, you might see the following error when loading a script:
Skipping loading `...` because it references outdated HarmonyWrapper and BepInEx.Harmony. To fix this, refer to github.com/denikson/BepInEx.ScriptLoader#upgrading-to-1240.
This error happens when using older ScriptLoader scripts with ScriptLoader 1.2.4.0 or newer.
In most cases, you can fix the script yourself. Open the script specified in the error into Notepad or some other text editor and do the following changes:
- Remove
using BepInEx.Harmony;
line - Replace
HarmonyWrapper.PatchAll
withHarmony.CreateAndPatchAll
Then try to run the game again. If the error persists or you get some other error, the script is too complex to fix by this guide. In that case please conact the developer of the script and ask them to fix it.
Starting with 2.0, you might notice an error such as: Use UnpatchSelf() to unpatch current instance...
This error happens due to scripts that were made for setups afflicted by the fixed issue above for why this fork was made.
In most cases, you can fix the script yourself. Open the script specified in the error into Notepad or some other text editor and do the following changes:
- Replace
Harmony.UnpatchAll(string)
withHarmony.UnpatchSelf()
Then try to run the game again. If the error persists or you get some other error, the script is too complex to fix by this guide. In that case please conact the developer of the script and ask them to fix it.