Convenience Modules

Reducing repeated code in your codebase

Something I would regularly see in other example code online is a constant redeclaration of various Unreal Systems:

def is_content_browser_loaded():
    asset_registry_helper = unreal.AssetRegistryHelpers()
    asset_registry = asset_registry_helper.get_asset_registry()
    return not asset_registry.is_loading_assets()

This can get tedious in larger pipelines if every function is using the first 1-5 lines to set up the asset registry or getting a subsystem. It also runs the risk of developers using different variable names for the same thing, causing inconsistencies.

Below is how I approach Unreal's subsystems and common libraries that I make use of

Setting up a Systems Module

Something I do in my work is have a dedicated module to setup the Asset Registry and Sub Systems. It's nothing fancy, it's just a module that looks something like this:

# file: systems.py

import unreal

# Registries and Libraries
asset_registry_helper = unreal.AssetRegistryHelpers()
asset_registry        = asset_registry_helper.get_asset_registry()
EditorAssetLibrary    = unreal.EditorAssetLibrary()
ToolMenus             = unreal.ToolMenus.get()
AssetTools            = unreal.AssetToolsHelpers.get_asset_tools()

# Subsystems
AssetEditorSubsystem   = unreal.get_editor_subsystem(unreal.AssetEditorSubsystem)
EditorActorSubsystem   = unreal.get_editor_subsystem(unreal.EditorActorSubsystem)
EditorAssetSubsystem   = unreal.get_editor_subsystem(unreal.EditorAssetSubsystem)
EditorUtilitySubsystem = unreal.get_editor_subsystem(unreal.EditorUtilitySubsystem)
LevelEditorSubsystem   = unreal.get_editor_subsystem(unreal.LevelEditorSubsystem)

For subsystems especially I often use the class name as-is, while this is not technically recommended in PEP8 I do this to remove any doubt as to what it is. This also comes with the added benefit of making it easier (lazier) to copy + paste into the Unreal Python Docs website

You may see this referenced in other parts of the Documentation, although I will try to limit it

Using the Module

In my other modules I start by importing the systems and libraries I need access to, these are then used in the functions as needed:

from systems import asset_registry

def is_content_browser_loaded():
    return not asset_registry.is_loading_assets()

Conveniences like this can really add up over the span of a pipeline, reducing the number of repetitive lines and ensuring consistency.

Last updated