Python in Unreal Engine — The undocumented parts
There are many tutorials on how to use python in Unreal Engine, however, they are often missing the interesting parts:
- how to get a subsystem in python
- how to return struct or array from a python function
- how to pip install package into Unreal Engine
In this article, I cover the more obscure examples that I had to find out the hard way. Let me start with simple things and gradually progress to more interesting stuff.
I also have to remind you that python (as provided by PythonScriptPlugin) is not usable a cooked game! You can use python only for your editor tools or in projects that do not require cooking.
Single-purpose script — How to automatically import a whole folder of assets
Create script UEProject\Content\Python\python_import_fbx.py
and use the following code:
import unreal
from pathlib import PathIMPORT_DIR = Path(r"G:\path\to\fbx_folder")
assert IMPORT_DIR.exists()tasks = []
for fbx in IMPORT_DIR.glob("*.fbx"):
asset_import_task = unreal.AssetImportTask()
asset_import_task.filename = str(fbx)
asset_import_task.destination_path = '/Game/Geometry'
asset_import_task.automated = True
tasks.append(asset_import_task)
asset_tools = unreal.AssetToolsHelpers.get_asset_tools()
asset_tools.import_asset_tasks(tasks)
You can import any assets this way, not just FBX files. You can also switch “automated” to False
to invoke an import dialog.
How to run python automatically on engine startup
Put file named init_unreal.py
in any Content\Python
folder and it will be run on startup of the engine.
How to get a reference to a subsystem in Python
aes = unreal.get_editor_subsystem(unreal.AssetEditorSubsystem)
Defining struct, enum and class in python and use it in a blueprint
In the following example, we can see how to define a struct, enum, and Blueprint Function Library to be usable in a blueprint. The enum and struct can be used throughout a blueprint as a type of variable.
Some important things to note:
- When declaring
ENUM
, you should use values of numbers from 0 to N. You can skip numbers but Unreal expects that there is always an enum value of 0. - Struct must inherit from
unreal.StructBase
or its subtype. It didn't work from me if I inherited from theunreal.Struct
. Fields in a struct are defined byunreal.uproperty
- Don’t forget to mark your blueprint library functions as static
In order for the function or type to be usable in blueprints, they must be either defined in or imported by Content\Python\init_unreal.py
file. As init_unreal.py
will be called on startup of the engine, making the definitions available to blueprints.
Using C++ types in python
If you declare a BlueprintCallable
(or BlueprintPure
) function: UBlueprintLibrary::MyCppFunction(int Num, TArray<FVector> Positions)
You can access it in python as:
unreal.BlueprintLibrary.my_cpp_function(num, pos)
Note that the name of the function is now in a snake_case (https://en.wikipedia.org/wiki/Snake_case)! You can pass it an ordinary python list of vectors and the list will be converted to TArray
internally.
How to use pip install with Unreal Engine
Method 1 — Using a command line
Using Unreal Engine python library, you can run the pip module:
C:\Program Files\Epic Games\UE_4.27\Engine\Binaries\ThirdParty\Python3\Win64\python.exe -m pip install numpy
Method 2 — Installing required packages automatically on Engine startup
This option is great when you work in a team and you don’t want to force your colleagues to “pip install” every time you update something. Use the following code in init_unreal.py, so it’s run on Unreal startup and installation happens transparently.
How to call python function through REST API
Remote Control API plugin (https://docs.unrealengine.com/4.27/en-US/ProductionPipelines/ScriptingAndAutomation/WebControl/QuickStart/)allows you to call functions remotely through REST from a different computer, phone, or tablet. You can call existing blueprint functions, but also your own C++ and Python types. Here is how to call python:
Having a Python file \Project\Content\Python\remote.py
and installing the type RemoteClass
to the engine by running the command: py remote.py
(in the Output window):
import unreal@unreal.uclass()
class RemoteClass(unreal.BlueprintFunctionLibrary):
@unreal.ufunction(static=True)
def remote():
print("Hello from remote!")
You can send a PUT request with the body:
{
"objectPath": "/Engine/PythonTypes.Default__RemoteClass",
"functionName": "remote"
}
The result is the text "Hello from remote!" logged into the Output window.
How to call python asynchronously from C++
FString PythonCommand(TEXT("SomePythonFunction()"));Future = FFunctionGraphTask::CreateAndDispatchWhenReady([=]
{
IPythonScriptPlugin::Get()->ExecPythonCommand(*PythonCommand);
});
Debugging python running in Unreal Engine
You can debug the python code running in embedded python in the engine! The official tutorial from EPIC is a block comment at Content\Python\debugpy_unreal.py
Python internals
The integration is done in the plugin PythonScriptPlugin
. Python decorators such as ustruct
, uenum
and function
are defined at PythonScriptPlugin\Content\Python\unreal_core.py
Those are then calling functions defined in C++ and accessed through the module _unreal_core