Loading...

Creating an editor module in Unreal Engine 4

Introduction

In this blog post I will provide an updated tutorial on how to add an editor module to Unreal Engine 4. This tutorial extends the slightly outdated Unreal wiki tutorial found here. I will assume you have a basic understanding of c++ and the Unreal Engine API.

Setting up a new c++ project

First off, we will create a brand new Unreal Engine 4 project. We’ll go for a c++ with the default template as this is irrelevant for this tutorial. I'll be naming the project Tutorial.

After creating the project, you can close Unreal Engine and open up the project folder. Open the generated .sln file (Tutorial.sln in our case). This will open Visual Studio as we will be working there for the most part.

If all went well, you should have a structure like this in your Solution Explorer


Setting up the Editor Module

The first step in creating an Editor Module is adding a new module entry in the .uproject file. By default it should look like this:

{
    "FileVersion": 3,
    "EngineAssociation": "4.20",
    "Category": "",
    "Description": "",
    "Modules": [
        {
            "Name": "Tutorial",
            "Type": "Runtime",
            "LoadingPhase": "Default"
        }
    ]
}

In the entry for Modules you can already see your Game Module called Tutorial added to the list. We are going to add a new entry just below our Game Module.

{
    "Name": "TutorialEditor",
    "Type": "Editor",
    "LoadingPhase":  "PostEngineInit"
}

"Name" Is the name of our editor module. It is good practice to add Editor as a postfix so that it easy to see what you're dealing with. "Type" is the type of module we're adding to the project. Valid entries for this are Runtime, RuntimeNoCommandlet, Developer, Editor, EditorNoCommandlet, and Program.

In our case we want to use Editor as we using it to create an editor module. This means that our module will only ever be loaded in our editor. This is something to keep in mind as you will not be able to use any logic in this editor module while in Runtime or Shipping.

Finally we have our "LoadingPhase" property. With this property we can determine when our module will be loaded by the engine. Possible options can be found here. Because our module has no dependencies we can use PostEngineInit. This will load our module after engine initialization.

The .uproject file should now look like this

{
    "FileVersion": 3,
    "EngineAssociation": "4.20",
    "Category": "",
    "Description": "",
    "Modules": [
        {
            "Name": "Tutorial",
            "Type": "Runtime",
            "LoadingPhase": "Default"
        },
        {
            "Name": "TutorialEditor",
            "Type": "Editor",
            "LoadingPhase":  "PostEngineInit"
        }
    ]
}

Folder structure

The folder structure for our editor module will essentially be the same as our game module. However, it is important to keep this code separate from the actual game code. Create a new folder under Source and rename it to TutorialEditor. Optionally you can use the same folder structure as the main module by adding Public and Private folders for more readability.

Module Build Rules

For the module to compile we need to create a .build.cs file. These .build.cs files are compiled by the UnrealBuildTool and constructed to determine the overall compile environment.

Create a new file called TutorialEditor.Build.cs under the TutorialEditor folder you just created and copy the contents from Tutorial/Tutorial.Build.cs into the new file. If you copied the contents from Tutorial/Tutorial.Build.cs it is important to rename the module names.

The new file should look like this

using UnrealBuildTool;

public class TutorialEditor : ModuleRules
{
    public TutorialEditor(ReadOnlyTargetRules Target) : base(Target)
    {
        PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
         PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });

        PublicDependencyModuleNames.AddRange(new string[] { "Tutorial" });

        PrivateDependencyModuleNames.AddRange(new string[] {  });

        //Only if you created the Public and Private folder paths
        PublicIncludePaths.AddRange(
            new string[]
            {
                "TutorialEditor/Public"
            });

        PrivateIncludePaths.AddRange(
            new string[]
            {
            "TutorialEditor/Private"
            });
    }
}

Note that I have added the project to the PublicDependencyModuleNames as we need our runtime module as a dependency

PublicDependencyModuleNames.AddRange(new string[] { "Tutorial" });

Editing the Target file

In the source folder you'll see the file TutorialEditor.Target.cs We'll have to make some small edits in here.

In the ExtraModuleNames array, we add a new entry to the editor module we created. So it will look like this:

ExtraModuleNames.AddRange( new string[] { "Tutorial", "TutorialEditor" } );

Note: As of version 4.19 it is no longer necessary to include the editor module in the runtime module build file. Source

Complete TutorialEditor.Target.cs:

using UnrealBuildTool;
using System.Collections.Generic;

public class TutorialEditorTarget : TargetRules
{
    public TutorialEditorTarget(TargetInfo Target) : base(Target)
    {
        Type = TargetType.Editor;
        ExtraModuleNames.AddRange( new string[] { "Tutorial", "TutorialEditor" } );
    }
}

Editor module source files

To actually be able to compile the editor module we'll need at least one header file and one source file. Go ahead and create a TutorialEditor.h file and place it under Source -> TutorialEditor -> Public if you created Public and Private directories. Otherwise, just put it in the Source->TutorialEditor directory. This file will act as the pre compiled header for the module so be sure to include anything that you think you'll need in most files here for faster compilation times.

We're also going to create a custom module class so we can load our customization once they're made, this is fairly similar to what you would see in a plugin. To do this create a class that extends IModuleInterface and at minimum override the StartupModule() and ShutdownModule() functions.

We don't actually have to create a new file for this. We'll put the class inside our TutorialEditor.h file. So it will look something like this:

#pragma once

#include "CoreMinimal.h"

#include "Modules/ModuleInterface.h"
#include "Modules/ModuleManager.h"
#include "UnrealEd.h"

DECLARE_LOG_CATEGORY_EXTERN(TutorialEditor, All, All)

class FTutorialEditorModule : public IModuleInterface
{
public:
    virtual void StartupModule() override;
    virtual void ShutdownModule() override;

};

To test if the module is loading correctly we added an extra line and declared a log category. As said in the wiki tutorial, since we know that this module will not be included in our shipping build, we can afford to use verbose log outputs.

DECLARE_LOG_CATEGORY_EXTERN(TutorialEditor, All, All)

The last thing we need to add is the .cpp file that belongs to the header file. So create a new file called TutorialEditor.cpp and put it in the Source -> TutorialEditor -> Private directory.

There are a few things to be done here. First, at the top of the file just below the #include's, use the IMPLEMENT_GAME_MODULE macro.

#include "TutorialEditor.h"
#include "Modules/ModuleManager.h"
#include "Modules/ModuleInterface.h"

IMPLEMENT_GAME_MODULE(FTutorialEditorModule, TutorialEditor);

The first argument is the name of the module class you created in the header file, the second argument is the name of the module as you declared it in the uproject file.

The last addition to this file is the basic implementation of the module function which we defined in the header file.

#define LOCTEXT_NAMESPACE "TutorialEditor"

void FTutorialEditorModule::StartupModule()
{
    UE_LOG(TutorialEditor, Warning, TEXT("TutorialEditor: Log Started"));
}

void FTutorialEditorModule::ShutdownModule()
{
    UE_LOG(TutorialEditor, Warning, TEXT("TutorialEditor: Log Ended"));
}

#undef LOCTEXT_NAMESPACE

The last step is regenerating the project files. We can do this by right clicking the .uproject file in Windows Explorer and clicking "Generate Visual Studio project files".

To see if our module is loading as expected, we need to build the editor from Visual Studio and check the Output Log. It should have logged "TutorialEditor: Warning: TutorialEditor: Log Started" when the module was loaded.

Be the first to comment

Post Comment

This website uses cookies to ensure you get the best experience on my website