Difference between revisions of "How to reload mod at runtime (UMM)"

From Nexus Mods Wiki
Jump to: navigation, search
(Created page with " This feature is added in version 0.14.0. You can compile assembly and load it into game without restarting. In Visual Studio, set the assembly version as "1.0.*". To su...")
 
Line 113: Line 113:
 
     }
 
     }
 
}</pre>
 
}</pre>
 +
 +
[[Category:Unity Mod Manager]]

Revision as of 14:26, 7 March 2019

This feature is added in version 0.14.0. You can compile assembly and load it into game without restarting.

In Visual Studio, set the assembly version as "1.0.*". To successfully load assembly, its version must be greater than the previous one. The "1.0.*" will allow the compiler to automatically increment the version number.

For convenience, configure the Post-build Event Command Line so that the assembly file is automatically copied to the game.

start XCOPY /Y /R "$(TargetPath)" "D:\Games\YourGame\Mods\$(ProjectName)\$(ProjectName).dll*"

In the source code of your mod, you need to specify UMM that the mod can be reloaded. Add this lines to EntryMethod.

modEntry.CanReload = true;
modEntry.OnUnload = Unload;

In mod options should appear Reloadbutton.

reload.png

You only need to create the Unload function and remove all patches and objects of old assembly. In fact, old assembly can not be unloaded. It stays in shadows and if we do not remove the scripts they can still work. I will write a few examples to make it clearer.

Another new field attribute is SaveOnReload. It allows to copy fields to your new assembly. But it works only with static fields and cannot copy the types created by your assembly.

using UnityEngine;
using UnityModManagerNet;

namespace ExampleMod
{
    static class Main
    {
        static bool Load(UnityModManager.ModEntry modEntry)
        {
            HarmonyInstance.Create(modEntry.Info.Id).PatchAll(Assembly.GetExecutingAssembly());
            #if DEBUG
            modEntry.CanReload = true;
            modEntry.OnUnload = Unload;
            #endif
            return true;
        }
        #if DEBUG
        static bool Unload(UnityModManager.ModEntry modEntry)
        {
            HarmonyInstance.Create(modEntry.Info.Id).UnpatchAll();
            
            return true;
        }
        #endif
        [HarmonyPatch(typeof(SomeClass), "Method")]
        static class SomeClass_Method_Patch
        {
            static void Prefix()
            {
            }
        }
    }
}
using UnityEngine;
using UnityModManagerNet;

namespace ExampleMod
{
    static class Main
    {
        [SaveOnReload] // Works
        public static string name;
        //[SaveOnReload] This does not work because the CustomObject from the old assembly and the new one is not the same.
        public static CustomObject obj;

        static bool Load(UnityModManager.ModEntry modEntry)
        {
            if (name == null)
                name = Game.GetNextName();
            obj = new GameObject(name, typeof(CustomObject))
            #if DEBUG
            modEntry.CanReload = true;
            modEntry.OnUnload = Unload;
            #endif
            return true;
        }
        #if DEBUG
        static bool Unload(UnityModManager.ModEntry modEntry)
        {
            GameObject.Destroy(obj);
            
            return true;
        }
        #endif
        class CustomObject : SomeGameObject
        {
        }
    }
}
using UnityEngine;
using UnityModManagerNet;

namespace ExampleMod
{
    static class Main
    {
        static bool Load(UnityModManager.ModEntry modEntry)
        {
            #if DEBUG
            modEntry.CanReload = true;
            #endif
            modEntry.OnGUI = OnGUI;
            return true;
        }

        static void OnGUI(UnityModManager.ModEntry modEntry)
        {
            if (GUILayout.Button("New button"))
            {
            }
        }
    }
}