Finding the Right Paths
Unreal offers a plethora of path and pointer types to reference assets, files on disk and objects in memory. I don’t want to go through all of the pointer variants here, or give explainers how to use each of them, but provide more of a cheat sheet for the different types of paths that you may encounter in the source code.
I’m also going to give some examples so you can identify them from their string representations.
Path Data Types
I usually go down the following mental list when deciding what kind of data type to store paths:
// link to an asset or object. use this to pick or load assets.
FSoftObjectPath ObjectPath;
// same as soft object path but limited to classes
FSoftClassPath ClassPath;
// prefer this when you need the package path and/or top level object name.
// can be serialized, but cannot be used to pick or load assets.
FTopLevelAssetPath TopLevelAssetPath;
// FString wrapper for uproperties that allows picking a directory path.
// Mostly needed for non-UFS files.
FDirectoryPath DirectoryPath;
// FString wrapper for uproperties that allows picking a file path.
// Rarely needed for anything dealing with uobjects, but may come in handy for non-UFS files.
FFilePath FilePath;
// should not be required to use outside the package loader itself, but has some utility functions for
// converting local into package path strings that might come in handy occasionally.
FPackagePath PackagePath;
// Names should be preferred for any repeatedly used names (e.g. package name) for faster lookups.
FName PackageName;
// Anything that imports/exports from files, clipboard, etc or need to do string manipulation needs FStrings.
// Move to one of the other formats (esp. TopLevelAssetPath, FSoftObjectPath, FName) if possible!
FString PackageNameString;
Path String Semantics
Often times you will just encounter some kind of path string and will need to make sense of what exactly it refers to. Let’s start with the most verbose type of paths, because it contains most of the components you will encounter on other path types:
/Script/Engine.Texture'/Game/Art/Textures/T_TreeBark.T_TreeBark'
I’m not aware of an official name for this string format for paths, but it’s used as text export format for any kinds of object pointers, e.g. when copy pasting a UObject pointer to clipboard in the editor. This path is actually a combination of two paths: A class path (e.g. /Script/Engine.Texture
) and an object path (e.g. /Game/Art/Textures/T_TreeBark.T_TreeBark
).
Class Paths
You will notice that class paths generally start with either /Script/
or /Game/
. Both of these prefixes are mounting points. /Script/
is used for paths to objects that contain type info for all the C++ classes and struct. Any C++ type decorated with a UCLASS
, USTRUCT
, UENUM
or UINTERFACE
macro will create a generated object in this location. UClass for example contains all the info about the class including its relationship to parent/child classes, implemented interfaces, functions and properties along with their metadata.
/Game/
is used for everything that originates not in C++ source code, but from within the game’s primary content directory, where most of your 3D assets, maps and blueprints will reside. Blueprints may of course also generate classes, but you need to distinguish the blueprint asset from the generated class! Similar as for C++ code, where the source is stored .h and .cpp text files, Blueprints have objects for the blueprint itself (e.g. /Game/Core/Player/BP_PlayerCharacter.BP_PlayerCharacter
) and the “generated” UClass recognizable by its _C
suffix (e.g. /Game/Core/Player/BP_PlayerCharacter.BP_PlayerCharacter_C
),
There are some other mounting points like /Plugin/
for plugin data, /Temp/
for temporary objects in the editor autosave chain, etc. You can also introduce custom mounting points, but it’s only really needed if you want to introduce a completely new data source to the engine, like I did for JSON data assets.
Every class has a “Class Default Object” (or CDO for short), which is a template to be used for instances of the class. The CDO will have the same name as the class with a Default__
prefix, so a blueprint CDO might be called Default__BP_PlayerCharacter_C
, making the whole text export path for the CDO:
/Game/Core/Player/BP_PlayerCharacter.BP_PlayerCharacter_C'/Game/Core/Player/BP_PlayerCharacter.Default__BP_PlayerCharacter_C'
Object vs Package Paths
You might have noticed that many paths you will encounter with Unreal have a duplicate asset name at the end separated by a dot (e.g. /Game/Art/Textures/T_TreeBark.T_TreeBark
). The reason for this is quite simple once you know about it: Any kind of object requires a “Package” object to handle all the saving and loading logic and one package may theoretically have multiple objects. For assets the name of the package and file on disk will usually be the same as the resource you want to save, so the name will match.
In-memory objects that are never saved may not have a package, but any asset that is actually saved on disk need a UPackage as top-level “outer” object. In C++ you can access an object’s package like this:
// path: /Game/Art/Textures/T_TreeBark.T_TreeBark
UTexture* MyTexture; // path: /Game/Art/Textures/T_TreeBark UPackage* MyPacakge = MyTexture->GetOutermost();
And to backtrack what I wrote 3 lines above: In-memory objects are usually discouraged from not having a package outermost. E.g. all class objects from C++ code are added to generated packages in /Script/ with one package per code module. And most dynamically allocated objects are added to the “transient package” by default.
Special Characters in Object Paths
As we said before, all class paths are object paths, so some general syntax applies to all of them. All of these Unreal internal paths refer to locations in the “Unreal File System” (UFS) - that may or may not correspond to locations in your regular OS file system - and use the following syntax:
/
forward slashes denote either- the start of a mounting point
- the end of directory name
.
dots denote subobjects. This means there are no “file extensions” with UFS paths!:
colons are used to separate the name of the first subobject and nested subobjects within that first subobject
This is all a bit abstract, so let’s look at somre more concrete examples in the next section…
Overview of Path Types
The engine terminology is not always consistent, so you might see some of these used interchangeably, e.g. object paths, full object paths, and object path names generally refer to the same thing.
Path Name | Example & Notes |
---|---|
Full Object Name | CharacterMovementComponent /Game/Core/Player/BP_PlayerCharacter.BP_PlayerCharacter:MovementComponent Used by some legacy systems, but is rarely used these days, because the class is just refered to by its name (not its full path). And the terminology doesn’t mesh well with other path types. |
(Full) Object Path (Name) | /Game/Art/Textures/T_TreeBark.T_TreeBark /Game/Core/Player/BP_PlayerCharacter.Default__BP_PlayerCharacter_C:MovementComponent.NestedSubObject /Game/Core/Player/BP_PlayerCharacter.Default__BP_PlayerCharacter_C:MovementComponent /Game/Core/Player/BP_PlayerCharacter.Default__BP_PlayerCharacter_C |
(Long) Package Name rarely: Package Path |
/Game/Core/Player/BP_PlayerCharacter See “Object vs Package Paths” above. Used by most systems that deal with assets, e.g. asset registry. |
Short Package Name | BP_PlayerCharacter Can be used by some systems for editor convenience, e.g. to refer to maps, but requires a whole asset registry scan to resolve, so discouraged from ever using outside developer tools |
Asset Name | BP_PlayerCharacter In 90% this will be the same as the short package name, but in the rare case that you have multiple assets in a single package, this might differ |
Local Path / File Name / Package File Name | ..\..\Content\Core\Player\BP_PlayerCharacter.uasset D:\YourGame\Content\Core\Player\BP_PlayerCharacter.uasset Unreal prefers paths relative to the executable, but will sometimes also use absolute paths. |
Mounting Point | /Game/ See “Class Paths” above |
Content Browser
The path types mentioned above will cover 99% of your needs, but something tripped me up when writing a custom content browser data source: The content browser maps the package hierarchy and “physical” file paths of your file system into a virtual file system for content browsing and therefore makes a distinction between internal and virtual paths (see EContentBrowserPathType):
- Internal path compatible with asset registry and engine calls, e.g.Â
/Plugin/PluginA/MyFile
- Virtual path for enumerating Content Browser data (may or may not start with /All depending on “show all folder” editor setting), e.g.Â
/All/Plugins/PluginA/MyFile
File System Paths
A bit of a tangential topic, but may be useful in this overview: The engine uses the following terminology for the components of file system paths:
- Clean Filename, e.g.Â
BP_PlayerCharacter.uasset
. This will be the same as a path’s “Leaf” for files. - Base Filename, e.g.Â
BP_PlayerCharacter
. This will be the clean filename without the extension. - Extension, e.g.Â
uasset
or.uasset
- no clear commitment on keeping or leaving the dot
Further Reading
It may be worth having a look at the engine source code of the following types, if you want to learn more about path handling in UE:
FPackageName
-> Utility class with static functions used for string based object/package path conversions.FPrimaryAssetId
-> refer to assets registered with the game’s asset manager by nameFAssetData
-> FAssetRegistry info on assets (including some class metadata)