Skip to content

How to create a mod for unity game

newman55 edited this page Sep 27, 2018 · 6 revisions

To begin with, these mods are more focused on creating scripts than content. But still make a new game object or texture, you can. Unity works on the csharp language, so creating a mod may seem hardcore, but you do not need to be a super programmer, it is enough to know the basic knowledge of programming. It will be even more difficult to dig into the game code in search of the necessary game functions.

Project creation

  1. Download and install Microsoft Visual Studio Community 2017 with C #
  2. Open the project creation and select 'Class Library (NET Framework)'. Change name to 'TestMod'. Open the project properties and target platform should be 'Net Framework 3.5' or 'Net Framework 4.0' for the newer Unity version.
  3. You need to add references to game files 'Assembly-CSharp.dll', 'Assembly-CSharp-firstpass.dll', '0Harmony12.dll', 'UnityEngine.dll', 'UnityEngine.UI.dll' which are located in 'Managed' folder of the game. If the unity version is 2017 or higher you need to add additional files 'UnityEngine.CoreModule.dll', 'UnityEngine.IMGUIModule.dll'. Now we can use the game and unity mod manager functions. Note - unity mod manager should already be installed.

Information file

Create an information file 'Info.json' so that the mod manager can read it and determine which files need to load when starting the game. The file is written in json and must be placed in the 'Mods' folder and one more folder e.g. '\Steam\steamapps\common\YourGame\Mods\TestMod\Info.json'.

{
  "Id": "TestMod",
  "DisplayName": "Test Mod",
  "Author": "newman55",
  "Version": "1.0.0",
  "ManagerVersion": "1.0.0",
  "Requirements": ["SomeMod-1.0.0", "AnotherMod"],
  "AssemblyName": "TestMod.dll",
  "EntryMethod": "TestMod.Main.Load"
}
* OR short variant
{
  "Id": "TestMod",
  "Version": "1.0.0",
  "EntryMethod": "TestMod.Main.Load"
}

* Id - Unique string. (Required)
* DisplayName - Name or Title. (Optional)
* Author - (Optional)
* Version - Need for dependent mods and to check for updates. (Required)
* ManagerVersion - Minimum required version of the mod manager. (Recommended)
* Requirements - Minimum required version of mods or just other required mod. (Optional)
* AssemblyName - Filename we are creating. Default like 'Id' (e.g. TestMod.dll). (Optional)
* EntryMethod - A function that will be called by the mod manager at load game. (Required)
* HomePage - Web address. (Optional)
* Repository - Web address to check for updates. (Optional)

Assembly file

The mod manager supports several variants of the 'Load' functions. Use only one.

using UnityEngine;
using Harmony12;
using UnityModManagerNet;

namespace TestMod
{
    static class Main
    {
        // Simply call.
        static void Load() 
        {
        }

        // Transfer a variable with data about the mod.
        static void Load(UnityModManager.ModEntry modEntry) 
        {
            // modEntry.Info - Contains all fields from the 'Info.json' file.
            // modEntry.Path - The path to the mod folder e.g. '\Steam\steamapps\common\YourGame\Mods\TestMod\'.
            // modEntry.Active - Active or inactive.
            // modEntry.Logger - Writes logs to the 'UnityModManager.log' file.
            // modEntry.OnToggle - The presence of this function will let the mod manager know that the mod can be safely disabled during the game.
            // modEntry.OnGUI - Drawing mod options.
            // modEntry.OnSaveGUI - Called while saving.
        }

        // Send a response to the mod manager about the launch status, success or not.
        static bool Load(UnityModManager.ModEntry modEntry)
        {
            return true; 
        }
    }
}

You can add a function that will control on/off mode. This function is optional.

using UnityEngine;
using Harmony12;
using UnityModManagerNet;

namespace TestMod
{
    static class Main
    {
        public static bool enabled;

        static bool Load(UnityModManager.ModEntry modEntry)
        {
            modEntry.OnToggle = OnToggle;
            return true;
        }

        // Called when the mod is turned to on/off.
        static bool OnToggle(UnityModManager.ModEntry modEntry, bool value /* active or inactive */)
        {
            enabled = value;
            return true; // Permit or not.
        }
    }
}

It remains the most important thing to add harmony patches. But it's better to read the official wiki. Here is an example.

using UnityEngine;
using Harmony12;
using UnityModManagerNet;

namespace TestMod
{
    static class Main
    {
        public static bool enabled;

        static bool Load(UnityModManager.ModEntry modEntry)
        {
            modEntry.OnToggle = OnToggle;

            var harmony = HarmonyInstance.Create(modEntry.Info.Id);
            harmony.PatchAll(Assembly.GetExecutingAssembly());

            return true;
        }

        static bool OnToggle(UnityModManager.ModEntry modEntry, bool value) 
        {
            enabled = value;
            modEntry.Logger.Log(Application.loadedLevelName);

            return true;
        }
    }

    [HarmonyPatch(typeof(Application), "loadedLevelName", MethodType.Getter)]
    static class Application_loadedLevelName_Patch
    {
        static void Postfix(ref string __result)
        {
            if (!Main.enabled)
                return;

            __result = "New Level Name";
        }
    }
}

Now the function 'Application.loadedLevelName' will always return "New Level Name" string. Similarly, we can change any value in the game.

Last, compile this code and copy the 'TestMod.dll' file to the 'Info.json' file. After starting the game, you will see messages in the 'UnityModManager.log' file. Also detailed log can be found in YourGame\YourGame_Data\output_log.txt or c:\Users%USERNAME%\AppData\LocalLow\YourGame\output_log.txt.

Additionally

You can explore the game code using the dnspy editor. Also available source code of my mods.

Clone this wiki locally