• MelonLogger: You can use LoggerInstance in non-static context of your mod class to log messages to the console. This is useful for debugging and providing feedback to the player. If you want to log messages in static context, MelonLoader provides a singleton instance of your mod class that you can use to access the logger:
Melon<MyMod>.LoggerInstance.Msg("This is a message from static context");

You also can use .Error or .Warning to log error or warning messages, respectively.

  • Callbacks: MelonLoader provides various callbacks that you can override in your mod class to execute code at specific points in the game lifecycle. For example, you can override OnUpdate to execute code every frame, or OnSceneWasLoaded to execute code when a new scene is loaded.
public override void OnUpdate()
{
    // This code will be executed every frame
    LoggerInstance.Msg("Updating..."); // Don't do this - it will spam the console and lag a lot!
}
public override void OnSceneWasLoaded(int buildIndex, string sceneName)
{
    // This code will be executed when a new scene is loaded
    LoggerInstance.Msg($"Scene {sceneName} was loaded!");
    if (sceneName == "Main")
    {
        LoggerInstance.Msg("We're loading the game!");
    }
}

You can also subscribe to events, using MelonEvents:

MelonEvents.OnUpdate.Subscribe(() =>
{
    // This code will be executed every frame
    Melon<MyMod>.LoggerInstance.Msg("Updating...");
}, 100); // The higher the number, the lower the priority.
  • MelonPreferences: MelonLoader provides a way to create preferences for your mod, which can be accessed and modified by the player in UserData/MelonPreferences.cfg or a custom file.

You can create preferences using the MelonPreferences.CreateCategory method, and then create preferences using MelonPreferences.CreateEntry method. Here’s an example:

private MelonPreferences_Category category;
private MelonPreferences_Entry<bool> entry1;

public override void OnInitializeMelon()
{
    category = MelonPreferences.CreateCategory("MyMod", "My Mod Preferences");
    entry1 = category.CreateEntry("EnableFeature", true, "Enable Feature", "This is a feature that can be enabled or disabled.");
}

public override void OnSceneWasLoaded(int buildIndex, string sceneName)
{
    if (entry1.Value)
    {
        LoggerInstance.Msg("Feature is enabled!");
    }
    else
    {
        LoggerInstance.Msg("Feature is disabled!");
    }
}

You can also use MelonPreferences.Save to save the preferences manually, if you want to save them at a specific point in time.

If you want to create a custom preferences file, use:

category.SetFilePath("Foo/Bar.cfg");
category.SaveToFile();
  • MelonEnvironment: Provides a way to access various paths related to the framework, such as the game directory, user data directory, and mod directory.
  • MelonCoroutines: MelonLoader provides a way to create coroutines, which are methods that don’t block the main thread and can be used to execute code over multiple frames. This is useful for tasks that take a long time to complete, such as loading assets or performing complex calculations.

You can create a coroutine using the MelonCoroutines.Start method, which takes a method that returns an IEnumerator. Here’s an example:

public override void OnSceneWasLoaded(int buildIndex, string sceneName)
{
    MelonCoroutines.Start(MyCoroutine());
}
private IEnumerator MyCoroutine()
{
    LoggerInstance.Msg("Starting coroutine...");
    yield return new WaitForSeconds(1f); // Wait for 1 second
    LoggerInstance.Msg("Coroutine finished!");
}

You can also use MelonCoroutines.Stop to stop a coroutine, if you need to.

MelonCoroutines.Stop(MyCoroutine());
// or pass in the object returned by `MelonCoroutines.Start` to stop a specific coroutine
object coroutine = MelonCoroutines.Start(MyCoroutine());
MelonCoroutines.Stop(coroutine);

Last updated 30 Jun 2025, 23:27 +0200 . history