Automate everything you can in Unreal Engine! You will thank me later
I love automating stuff in Unreal Engine because it makes both the development process less frustrating and finding crucial issues way easier. When it comes to the topic of automation in the UE, there are 2 main topics to cover:
Scripting the editor
The editor scripting is important when you want to set similar data in multiple assets or Actors in the level, or if you want to find some specific data in your Content folder. Do you want to set some properties in multiple assets? Recompile and resave many Blueprints at once? Or find assets with specific properties? If so, this is where the editor automation should come in.
Creating editor scripts is relatively easy because you should be able to automate quite a lot of things by using Blueprints only — Editor Utility Blueprints and Editor Utility Widgets, to be more precise. They are called Editor Utilities or Blutilities.
However, I highly encourage you to use Python for scripting the editor as well. There are several advantages to using it:
- Unreal Python API allows you to use not only all the
BlueprintCallable
functions but also some functions that by default are available in C++ only (for instance,UObject::Modify
). - Python scripts are text files so they can be easily modified and merged by multiple people at once.
- With Python, you can use StartupScripts that are triggered right after the Engine initialization. You can set them up in Project Settings->Plugins->Python.
Btw, you can create Blueprint Function Libraries in Python as well.
You shouldn’t really need C++ for the editor automation. Combining Editor Utility BPs with Python should be more than enough most of the time. But sometimes you might need to write static helper functions in C++ if you need a functionality that is missing in the engine by default.
Automation tests
Even though automation tests and automating the editor sound similar, they are handled by a bit different frameworks. Most of the automation tests should be written in C++ because the FAutomationTestBase
structure exists outside of the UObject
ecosystem. However, some tests can be created in BP too (I will talk about them later).
The most crucial thing to add is the IMPLEMENT_SIMPLE_AUTOMATION_TEST
or IMPLEMENT_COMPLEX_AUTOMATION_TEST
macro. You need to define a test tag and test flags in it. Then, the only virtual function you need to override is FAutomationTestBase::RunTest
(or together with the FAutomationTestBase::GetTests
function, if you’re making a complex test).
IMPLEMENT_SIMPLE_AUTOMATION_TEST(FPlaceholderTest, "TestGroup.TestSubgroup.PlaceholderTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::MediumPriority | EAutomationTestFlags::ProductFilter)
bool FPlaceholderTest::RunTest(const FString& Parameters)
{
// you can use those functions to print the test results
const FString LogMessage = TEXT("TestLog");
AddInfo(LogMessage);
AddWarning(LogMessage);
AddError(LogMessage);
return true;
}
You can trigger the test from the Command Line by using the tag (EzArgs plugin for Rider or UnrealVS plugin for Visual Studio will be useful to do that):
-skipcompile -execcmds=”Automation RunTests TestGroup.TestSubgroup.PlaceholderTest$;Quit” -stdout -unattended -NOSPLASH -NullRHI
That means you can trigger automation tests by using CI/CD (Jenkins, TeamCity). You can test your game 24/7, even when you sleep! 🎉
You can also run your tests through the UE Editor. First of all, make sure that the Functional Testing Editor plugin is enabled.
Then, go to Tools->Test Automation. You can easily trigger multiple tests at once there.
Functional Tests
If you enable the Functional Testing Editor plugin, you can now create Functional Tests too. The Functional Test class inherits from an Actor and is supposed to test runtime features. Functional Tests can be created in BP, but Editor Functional Tests have to be created in BP because if you open the header file of that class, you will notice that it has Blueprintable
and MinimalAPI
macros — which means you cannot create a C++ class that inherits from the AEditorFunctionalTest
class, but you can create a BP that inherits from it:
Here are the most important events and functions provided by a Functional Test class:
After creating your Functional Test Actor, simply put it on your map. Now, its test tag should be automatically generated in the Testing Automation Frontend window:
Editor Tests
If you enable the Editor Tests plugin, you can use a new Editor Utility Blueprint class — Editor Utility Test. That means you can create editor tests in BP too.
Similar to Functional Tests, Editor Utility Tests should be automatically visible in the Testing Automation Frontend as well:
Moreover, you can use those tags to trigger both Functional Tests and Editor Utility Tests from the Command Line! 🎉
Example Tests
Recently I created a plugin called Editor Test Utilities. It’s basically a package of automation tests for common asset issues. With tests provided, you can test issues like:
- Too complex asset dependency/reference chain of the Player Pawn
- Assets with too big size map (disk size)
- Meshes with too big triangle count
- Blueprints with empty ticks or ticks enabled by default
- Blueprints that use functions like “GetAllActorsOfClass”
- Blueprints that use pure functions with multiple outputs
- User Widgets that use bindings
- Redirectors in the project
I also provided Python scripts that trigger those tests. Those scripts can be executed during the editor startup. If a test from a script fails, it will generate a notification in the Message Log (if the test is passed successfully, no notification should be added to the Message Log during the editor startup).
The package contains some Editor Functional Tests too.
Those tests should help you maintain the project in a good state.
Other useful stuff
Do you like my articles? Please consider supporting me. Thank you!