-
Notifications
You must be signed in to change notification settings - Fork 2
Custom Gamemode Tutorial
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!");
}
}
}
Quick Start
Step-by-step Mapping Guides
- Setting up your environment
- Creating your first map
- Creating custom scripts
- Creating in-game menus
Mapping References