Skip to content

Custom Gamemode Tutorial

Frityet edited this page Nov 27, 2020 · 2 revisions

Custom gamemodes are a way to create custom behaviour which effects what is happening in game. It is based off already existing gamemodes which are loaded with base game scenes, such as MeatFortress.

To create a custom gamemode, it is required to have a CustomSceneLoader and a SceneExporter class which define how the scenes are loaded and exported respectively. CustomSceneLoader can be found in the WurstMod.Runtime namespace, inside the WurstMod.dll assembly. The SceneExporter can be found in the WurstMod.UnityEditor.SceneExporters namespace in the WurstMod.dll assembly.

using WurstMod.Runtime;
using WurstMod.UnityEditor.SceneExporters;

namespace WurstMod.Gamemodes
{
    public class TutorialLoader : CustomSceneLoader
    {
        
    }

    public class TutorialExporter : SceneExporter
    {
        
    }
}

Your script right now should look something like this

Now you have probably noticed that there are errors on these scripts. This is because the classes still need data inside it to function.


First we will be configuring the CustomSceneLoader class.


The first line we need to add is defining the GamemodeID, which is is a unique identifier of the gamemode.

public override string GamemodeId => "[Gamemode ID here]";

For [Gamemode ID here] add a unique title which describes your gamemode, for example, anton.meatfortress.

The second line which is required to be added is defining the base game scene we are basing our gamemode off of.

public override string BaseScene => "[Base H3VR Scene you want the map to be based off of]";

For [Base H3VR Scene you want the map to be based off of], use any of the "scene name" category strings, for example, MF2_MainScene

The next lines you will need to write are a function, PostLoad(), which is what will run after the scene is loaded.

public override void PostLoad()
{
    //put anything here
}

Most commonly, there would be a message written to the console which confirms that the scene has loaded. We can achieve this by using Debug.Log() which is a function in the UnityEngine.Logging namespace in the UnityEngine.dll assembly.

public override void PostLoad()
{
    Debug.Log("Tutorial Gamemode Loaded");
}

The next thing that you must add is a string array called DestroyOnLoad which defines what GameObjects from the base scene (ex. the table in proving grounds) are going to be destroyed on game load. These can be root GameObjects, so you do not have to specify each object.

 public override string[] DestroyOnLoad => new[]
{
     "Object you want to destory on load 1",
     "Object you want to destroy on load 2"
}; //arrays end in ;

For example, these are all the GameObjects which comprise Your script should now look something like this:

using WurstMod.Runtime;
using WurstMod.UnityEditor.SceneExporters;
using UnityEngine;

namespace WurstMod.Gamemodes
{
    public class TutorialLoader : CustomSceneLoader
    {
        public override string GamemodeId => "frityet.tutorialGamemode";

        public override string BaseScene => "MF2_MainScene";

        public override void PostLoad()
        {
            Debug.Log("Started Gamemode");
        }
        
        public override string[] DestroyOnLoad => new[]
        {
            "_Animator_Spawning_",
            "_Boards",
            "_Env",
            "AiLadderTest1"
        };
    }

    public class TutorialExporter : SceneExporter
    {
        
    }
}

Now we will be configuring the SceneExporter class


The first line you need for this class is to copy and paste the GamemodeID string from the CustomSceneLoader class. In my example I would copy the line

public override string GamemodeId => "frityet.tutorialGamemode";

and put it in the SceneExporter class.

The GamemodeID must be the same in both classes!

Next, we need to add a function, Validate, which validates the scene on export to ensure it would work. This function must have the arguments scene, CustomScene, and ExportErrors to properly function.

public override void Validate(scene scene, CustomScene root, ExportErrors err)
{

}

Right now, this validate function does nothing, until we tell it what to do. We can do this easily by using the function base.validate() with the arguments scene, root, err.

base.validate(scene, root, err);

Since we are now overriding the validate method, we will call the base validate method to ensure that the code there still runs too.

We can also add additional checks, such as ensuring their is a type of a component in a GameObject in the scene.

RequiredComponents<>();

In the <> you would put the custom component (which is a class)

RequiredComponents<RigidBody>();

Inside the parenthesis, there are 4 arguments, the first argument is required, and that is the minimum number of components required in the scene

RequiredComponents<RigidBody>(1);

The second argument is the MAXIMUM components in the scene, if you dont specify this one, it will default to int.MaxValue , which is 2,147,483,647

RequiredComponents<RigidBody>(1, 10);

Now this check would work fine, however for more customisation you can give 2 more arguments, the first being a boolean which defines if the error is a warning (so it can be ignored) or an error (cant be ignored), the default is false

RequiredComponents<RigidBody>(1, int.MaxValue, true);

The last argument you can give is a string which is the error/warning message which shows.

RequiredComponents<RigidBody>(1, int.MaxValue, true, "You should add more RigidBodies!");

That is all you need to create a custom gamemode!

In the end, your script should look something like this (but with different specifics)

using WurstMod.Runtime;
using WurstMod.UnityEditor.SceneExporters;
using UnityEngine;
using UnityEngine.SceneManagement;
using WurstMod.MappingComponents.Generic;
using WurstMod.MappingComponents.Sandbox;
using WurstMod.UnityEditor;

namespace WurstMod.Gamemodes
{
    public class TutorialLoader : CustomSceneLoader
    {
        public override string GamemodeId => "frityet.tutorialGamemode"; //Example: anton.meatfortress

        public override string BaseScene => "ProvingGrounds"; //Example: MF2_MainScene

        //After the map is loaded, this method will be called
        public override void PostLoad()
        {
            Debug.Log("Started Gamemode");
        }
        
        public override string[] DestroyOnLoad => new[]
        {
            "_Animator_Spawning_",
            "_Boards",
            "_Env",
            "AiLadderTest1"
        };
    }

    public class TutorialExporter : SceneExporter
    {
        public override string GamemodeId => "frityet.tutorialGamemode";
        public override void Validate(Scene scene, CustomScene root, ExportErrors err)
        {
            base.Validate(scene, root, err);
            base.
            RequiredComponents<GameObject>(5, int.MaxValue, true, "You should add more GameObjects!");
        }
    }
}
Clone this wiki locally