Printing UObject information

Sometimes to implement a feature in our game we need to know how Unreal Engine works internally, there are a lot of ways to do this: finding any information on the web, reading the engine codes, debugging the program at some point, printing things to the log, and many more.

In this blog post I would like to share some codes that can help us in printing information to the log in order to understand how Unreal Engine works. Without further ado, these are the source codes :

http://pastebin.com/YZex4TRD

There are some debugging functions in the source codes, but the most important one is the TraceObject function.

// Flags for TraceObject
#define TOF_OBJECT_DETAILS     0x01
#define TOF_CLASS_DETAILS      0x02
#define TOF_PROPERTY_DETAILS   0x08

#define TOF_ALL_DETAILS            0xff
#define TOF_NONE               0x00
// End of flags for TraceObject

/**
* Print information of an object to the log.
* @note: This function only works in debug builds. (DebugGame or DebugGameEditor), it does nothing in Development or Shipping build.
* @param    Object                  The object whose information will be written to the log.
* @param    Title                   The title that will be added at the beginning of the information.
* @param    PropertyNameToTrace     List of property names to be included in the the information.
* @param    TraceObjectFlags        Bit flags of what details to be added to the information, the default value is to print all details.
*/
GAME_API void TraceObject( const UObject* Object, const FString& Title = TEXT(""), const TArray<FName>& PropertyNamesToTrace = TArray<FName>(), int32 TraceObjectFlags = TOF_ALL_DETAILS  );

This function is also a part of the game module that I am currently working on ( it’s still far from completio n) that you can get at : https://github.com/fathurahman/game-modules

Usage

Using the TraceObject function is very simple, at the very least you just have to specify the Object that you wish to print and a title that will be written at the beginning of the logs. e.g: `TraceObject( MyObject, TEXT(“Just a test”) ).

If you wish to print information about some properties in the object, you can specify the PropertyNamesToTrace parameter. e.g:

TArray&amp;amp;amp;lt;FName&amp;amp;amp;gt; PropertyNames;
PropertyNames.Add( &amp;amp;amp;quot;Foo&amp;amp;amp;quot; );
PropertyNames.Add( &amp;amp;amp;quot;Bar&amp;amp;amp;quot; );
TraceObject( MyObject, TEXT(&amp;amp;amp;quot;Just another test&amp;amp;amp;quot;), PropertyNames );

There are three categories of information that can be printed by TraceObject function: Object details, Object’s class details, and the last one is property details. By default TraceObject will print all of them but you can control what details should be printed to the log by specifying the TraceObjectFlag.

For example if you do not specify the TraceObjectFlags or you’re using TFO_ALL_DETAILS then it will print out a lot of information. e.g:

LogTrace: OnMatchStateSet [GameState_0] : 
LogTrace:   Object URL    : GameState /Game/Maps/UEDPIE_0_Map_Test.Map_Test:PersistentLevel.GameState_0
LogTrace:   Object Flags  : RF_Transactional RF_Transient 
LogTrace:   Class URL      : Class /Script/Engine.GameState
LogTrace:   Class Flags    : CLASS_Native CLASS_NotPlaceable CLASS_RequiredAPI CLASS_TokenStreamAssembled CLASS_HasInstancedReference CLASS_Intrinsic CLASS_Constructed 
LogTrace:   Class Hierarchy: Object-&amp;amp;amp;gt;Actor-&amp;amp;amp;gt;Info-&amp;amp;amp;gt;GameState
LogTrace:   Property : MatchState
LogTrace:     URL    : NameProperty /Script/Engine.GameState:MatchState
LogTrace:     Flags  : CPF_Edit CPF_BlueprintVisible CPF_BlueprintReadOnly CPF_Net CPF_ZeroConstructor CPF_DisableEditOnTemplate CPF_EditConst CPF_IsPlainOldData CPF_RepNotify CPF_NoDestructor CPF_Protected CPF_HasGetValueTypeHash CPF_NativeAccessSpecifierProtected 
LogTrace:     Value  : EnteringMap
LogTrace:   Property : PreviousMatchState
LogTrace:     URL    : NameProperty /Script/Engine.GameState:PreviousMatchState
LogTrace:     Flags  : CPF_Edit CPF_BlueprintVisible CPF_BlueprintReadOnly CPF_ZeroConstructor CPF_DisableEditOnTemplate CPF_EditConst CPF_IsPlainOldData CPF_NoDestructor CPF_Protected CPF_HasGetValueTypeHash CPF_NativeAccessSpecifierProtected 
LogTrace:     Value  : EnteringMap

But if you specify TFO_PROPERTY_DETAILS | TFO_OBJECT_DETAILS then the class information will not be printed:

LogTrace: OnMatchStateSet [GameState_0] : 
LogTrace:   Object URL    : GameState /Game/Maps/UEDPIE_0_Map_Test.Map_Test:PersistentLevel.GameState_0
LogTrace:   Object Flags  : RF_Transactional RF_Transient 
LogTrace:   Property : MatchState
LogTrace:     URL    : NameProperty /Script/Engine.GameState:MatchState
LogTrace:     Flags  : CPF_Edit CPF_BlueprintVisible CPF_BlueprintReadOnly CPF_Net CPF_ZeroConstructor CPF_DisableEditOnTemplate CPF_EditConst CPF_IsPlainOldData CPF_RepNotify CPF_NoDestructor CPF_Protected CPF_HasGetValueTypeHash CPF_NativeAccessSpecifierProtected 
LogTrace:     Value  : EnteringMap
LogTrace:   Property : PreviousMatchState
LogTrace:     URL    : NameProperty /Script/Engine.GameState:PreviousMatchState
LogTrace:     Flags  : CPF_Edit CPF_BlueprintVisible CPF_BlueprintReadOnly CPF_ZeroConstructor CPF_DisableEditOnTemplate CPF_EditConst CPF_IsPlainOldData CPF_NoDestructor CPF_Protected CPF_HasGetValueTypeHash CPF_NativeAccessSpecifierProtected 
LogTrace:     Value  : EnteringMap

Example Use Case

I have used this function frequently to study how Unreal Engine works, and I must say that it is one of the most useful method for me to learn Unreal Engine.

One of the things that I have done with this function was when I needed to know what objects are instantiated from a certain actor class that I have made, I call the TraceObject function in the class Constructor, PostInitProperties, PostLoad, PostEditImport, Serialize and OnConstruction, I created a blueprint using this class as its parent and spawn the blueprint actor into the editor world and save the map, from the log I learned a lot of useful things, I learned about the existence of a skeleton object inside a blueprint, I learned how Unreal Engine copies the class default object to instanced object, I learned the process of duplicate an actor in the editor, and many more, all just by reading the log while sipping a cup of hot coffee.

One other useful thing that you have probably known is that the log can be quite cluttered with many different things, especially in debug build, thus having a tool to filter the logs will be really useful, I personally use the many different text processing tools provided by Bash (grep, sed, sort, unique, etc.); You can also turn off some log categories that you don’t really care about, but it’s a lot of work and you will most likely missed out some important information by turning off those logs.

Hopefully the function that I have shared in this blog post will be useful for you as it has been for me.

Flexible Data with UStruct

In game prototyping or pre-production we usually don’t know what kind of data we are going to use, these data will probably change in each iteration as we are trying to figure out the mechanics of our game, and as our code base get larger these changes will be more and more expensive to make and harder to manage. What I am going to show you in the article is an easy and effective way to manage this kind of problem in Unreal Engine 4.

Case Study

For the purpose of explaining the method, I am going to use a simple problem as case study, let’s say that we are making an RPG game in Unreal Engine 4 using C++ and in this game we have combat stats that looks something like this:

  • Health
  • Mana
  • Attack
  • Defense

We decided that the final combat stats of a character is calculated using this formula:

CombatStats = CombatStatsBase + CombatStatsModifier

The CombatStatsModifier is the sum of all CombatStats from the many elements that the character has such as from equipments, from status effects, from abilities, etc. Each component may need some common Arithmetic operations such as addition, multiplication, substraction, etc for generating its CombatStats. For example, the Health of a specific armor is 0.2 times the CombatStatBase of its user.

We have also decided to have an in-game UI that we can toggle at runtime to show the values of each member in CombatStats.

Let’s say that at any point in the development we may expand or change the CombatStats, maybe to something like this:

  • Health
  • Stamina
  • Mana
  • Attack
  • Defense
  • Intelligence
  • Hit
  • Dodge
  • MovementSpeed
  • AttackSpeed

Now from the case study above, we can extract these requirements:

  • CombatStats member variables may change in the future.
  • The final number of members in CombatStats may be more than 10.
  • Two CombatStats can be multiplied, divided, added, or substracted.
  • Since there will be multiplication and division with a fraction (e.g armor adds 20% health), the member should be a floating point number instead of an integer.
  • The user interface should show each of the member’s name, base value, and modifier value.

You must have encounter similar thing in your own game development process especially if you are using pre-production step or using some kind of agile game development practice that embraces changes in order to make a fun game.

Data Structure

First of all, we need to create the data structure for combat stats:

USTRUCT(BlueprintType, meta=(HiddenByDefault))
struct FCombatStats
{
    GENERATED_USTRUCT_BODY()

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="CombatStats")
    float Health;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="CombatStats")
    float Mana;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="CombatStats")
    float Attack;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="CombatStats")
    float Defense;

    // Arithmetic operators
    FCombatStats operator*(const FCombatStats& Other) const;
    FCombatStats operator/(const FCombatStats& Other) const;
    FCombatStats operator+(const FCombatStats& Other) const;
    FCombatStats operator-(const FCombatStats& Other) const;
    // End of Arithmetic operators
};

Now lets look at the unreal struct metadata, we specified BlueprintType because we want this struct to be exposed to blueprint for obvious reasons that I do not need to explain, and the second one is HiddenByDefault which means that we told unreal to not show the pin when we break or make the structure in blueprint, the reason is because we will have more than 10 members, exposing all of them will be quite messy and we’re not going to need all of them anyway in most of our blueprint graphs.

Arithmetic Operator

In the struct declaration, we declared several Arithmetical operators, this is one of them:

FCombatStats FCombatStats:operator*(const FCombatStats& Other) const
{
    const float * const SelfPtr = reinterpret_cast<const float * const>( this );
    const float * const OtherPtr = reinterpret_cast<const float * const>( &Other );

    FCombatStats Result;
    float* ResultPtr = reinterpret_cast<float*>( &Result );
    int32 ElementNum = sizeof(FCombatStats) / sizeof(float);
    for (int32 i = 0; i < ElementNum; i++)
    {
        ResultPtr[i] = SelfPtr[i] * OtherPtr[i];
    }

    return Result;  
}

This operator is flexible and does not need to be changed if we modify or extend the members of FCombatStats. We can also say that the operator is independent or decoupled from the data. Other operators in this struct are similar to this one.

Blueprint Function Library

The operators the we have made are for C++, they are not accessible from Blueprint, to do that we need to make a Blueprint function library, it is quite simple and looks something like this:

UCLASS()
class UCombatStatsStatics : public UBlueprintFunctionLibrary
{
    GENERATED_BODY()
public:

    UFUNCTION(BlueprintPure, Category="CombatStats", meta=(DisplayName="CombatStats * CombatStats", CompactNodeTitle="*", Keywords="* multiply", CommutativeAssociativeBinaryOperator = "True"))
    static FCombatStats Multiply_CombatStatsCombatStats( FCombatStats A, FCombatStats B ) { return A * B; }

    UFUNCTION(BlueprintPure, Category="CombatStats", meta=(DisplayName="CombatStats / CombatStats", CompactNodeTitle="*", Keywords="/ divide"))
    static FCombatStats Divide_CombatStatsCombatStats( FCombatStats A, FCombatStats B ) { return A / B; }

    UFUNCTION(BlueprintPure, Category="CombatStats", meta=(DisplayName="CombatStats + CombatStats", CompactNodeTitle="+", Keywords="+ add plus", CommutativeAssociativeBinaryOperator = "True"))
    static FCombatStats Add_CombatStatsCombatStats( FCombatStats A, FCombatStats B ) { return A + B; }

    UFUNCTION(BlueprintPure, Category="CombatStats", meta=(DisplayName="CombatStats - CombatStats", CompactNodeTitle="-", Keywords="- substract minus"))
    static FCombatStats Substract_CombatStatsCombatStats( FCombatStats A, FCombatStats B ) { return A - B; }

};

The functions have many meta data and almost all of their purpose are to make the blueprint graph much cleaner, and the other important purpose is to make them usable in one of the best feature in Blueprint, the Add Math Expression node that basically enables Blueprint user to type mathematical expression instead of creating dozens of haywire nodes that are hard to read and manage.

Since these functions are basically calling the C++ operators, they are automatically become as flexible as the operators.

User Interface

The last one is the User Interface, we are using UMG (Unreal Motion Graphics) and we make a widget, WB_CombatStatWidget, that displays a single member of FCombatStats and then we make another widget, WB_CombatStatsPanel, that creates as many WB_CombatStatWidget as the number of members in FCombatStats and arrange them in a vertical box.

I am not going to go further into UMG as it is not within the scope of this article, but I am going to show you one of the most important function in the c++ parent class of WB_CombatStatsPanel. But before that let’s have a look at what we are trying to display in WB_CombatStatWidget, it is something like this:

[NameText] : [BaseValueText] ( +/- ModifierValueText )

The ModifierValueText is optional, the text may not visible if the modifier value is 0 and it is also colored differently when it has negative value (red) as opposed to positive value (green). This is a common representation of a character stat in most RPG or Strategy games such as Diablo, Torchlight or Dota 2; The data for WB_CombatStatWidget is:

USTRUCT(BlueprintType)
struct FCombatStatWidgetData
{
    GENERATED_USTRUCT_BODY()

    UPROPERTY(BlueprintReadWrite, Category="UI")
    FText NameText;

    UPROPERTY(BlueprintReadWrite, Category="UI")
    FText BaseValueText;

    UPROPERTY(BlueprintReadWrite, Category="UI")
    FSlateVisibility ModifierValueTextVisibility;

    UPROPERTY(BlueprintReadWrite, Category="UI")
    FLinearColor ModifierValueTextColor;

    UPROPERTY(BlueprintReadWrite, Category="UI")
    FText ModifierValueText;
};

Now, this data will be fed to each WB_CombatStatWidget created by WB_CombatStatsPanel, and WB_CombatStatsPanel get these data from this function below:

void UCombatStatsPanel::GetCombatStatWidgetDataList( const FCombatStats& BaseStats, const FCombatStats& ModifierStats, TArray<FCombatStatWidgetData>& OutDataList ) const
{
    UScriptStruct* CombatStatsStruct = FindObject<UScriptStruct>( nullptr, TEXT("/Script/MyProject.CombatStats") ); 

    OutDataList.Empty();

    for ( TFieldIterator<UFloatProperty> It(CombatStatsStruct); It; ++It )
    {
        UFloatProperty* Prop = *It;
        float BaseStat = Prop->GetFloatingPointPropertyValue( (void const *)(&BaseStats) );
        float ModifierStat = Prop->GetFloatingPointPropertyValue( (void const *)(&ModifierStats) );

        FCombatStatWidgetData Data;
#if WITH_EDITOR
        Data.NameText = Prop->GetDisplayNameText();
#else
        // TODO: create a lookup for member name or resources, but for now just use the name of the property
        Data.NameText = FText::FromString( Prop->GetName() );
#endif
        Data.BaseValueText = FText::AsNumber( BaseStat );
        if ( ModifierStat == 0 )
        {
            Data.ModifierValueTextVisibility = ESlateVisibility::Hidden;
        }
        else
        {
            Data.ModifierVisibility = ESlateVisibility::Visible;

            if ( ModifierStat > 0 )
            {
                Data.ModifierValueTextColor = FColor::Green;
                Data.ModifierValueText = FText::FromString( FString::Printf( TEXT("+ %.0f"), ModifierStat ) );
            }
            else
            {
                Data.ModifierValueTextColor = FColor::Red;
                Data.ModifierValueText = FText::FromString( FString::Printf( TEXT("- %.0f"), FMath::Abs(ModifierStat) ) );
            }
        }

        OutDataList.Add( Data );
    }
}

As you can see in the code, we are not doing brute force by writing it like this:

// Health
Data.NameText = LOCTEXT("Health", "Health");
Data.BaseValueText = FText::AsNumber( BaseStats.Health );
Data.ModifierValueText = FText::AsNumber( FMath::Abs(ModifierValue.Health) );

...

// Defense
Data.NameText = LOCTEXT("Defense", "Defense");
Data.BaseValueText = FText::AsNumber( BaseStats.Defense );
Data.ModifierValueText = FText::AsNumber( FMath::Abs(ModifierValue.Defense) );

That would not be flexible and very tightly coupled to the data declaration, what we have written are codes that are using the Unreal Engine reflection system, we iterate each of the float properties in that struct and populate the widget data from each of them, this is flexible and we do not need to change it if we modify the FCombatStats as long as it conforms to the rule of having all of the members to be a float point type.

Conclusion

By using this method we can easily modify the FCombatStats as much as we want without needing to rewrite the Arithmetic operators, UI codes, and many other codes that uses FCombatStats.

I have used this method in my project, it works well in both the editor and shipped game, it has significantly increased the speed of the development iterations, and I can focus on more important stuff of actually making the game fun.

One thing what I am worried about is the reinterpret casts in the Arithmetic operators, but if Unreal Engine has managed the endianness of the underlying platform (and I believe it has) then it wouldn’t be a problem, and as far as I know the only platforms that uses big-endian are IBM servers, which I don’t think has a large market share for games, they are.. well.. servers, that are meant to run non-game applications. But if you want to be on the safe side, you can use similar techniques as the UI codes which is iterating the script struct properties.

Inside of Unreal Engine Blueprint

blueprint

Blueprint is a great new feature in Unreal Engine 4, it is a visual scripting that enables everybody including non-programmers to easily creates and tweak Gameplay elements in the game, the tools to make and edit them in the editor are very rich and extendable.

As a game programmer, apart from using Blueprint as a mean to prototype a feature, we may want to extend and customize it to meet the requirements of the game we are working on, extending the blueprint comes in many different flavors, adding a custom blueprint elements in C++ is very easy, we only need to create various C++ functions and properties that are accessible from Blueprint, but sometimes it is not quite enough for us, sometimes we need to create a custom nodes that our game designer can easily use, create an automated process related to blueprint such as collecting blueprint classes, create a utility to convert our custom game actors or data into Blueprints, and many more, this is especially true if you are a tool programmer and trying to optimize the pipeline of your game.

To do an advanced customization of Blueprint, we need to know what is a Blueprint, what is really happening inside of it, what are the data, how does it generates its output, etc. This article is an overview of the answers to all of these questions. It is a part of my study that I want to share with you, in the hope that we can utilize Unreal Engine 4 to its full potentials in order to make a better game with it and especially to increase our productivity by making convenient and optimized tools that are related to Blueprint as part of our game production pipeline.

I will refer to this advance type of Blueprint customization simply as Blueprint customization. This article assume that you have already known Blueprint from end user perspective and also a bit of knowledge in CoreUObject, AssetRegistry, and UnrealEd modules.

What is a Blueprint?

In the simplest sense, Blueprint is just a black box that uses ParentClass as input and produces BlueprintGeneratedClass as output;  A very simple definition of Class would be a collection of information about properties and functions of an Object, and an Object itself is just a series of bytes, thus, a Class is some kind of map for us to know what a certain Object really is.

blueprint-blackbox

Blueprint itself is an asset, it is not a Class, this asset will not be cooked in the final package of our game, which means, we should never reference a Blueprint asset at run-time.

Blueprint is meant to be used in the editor, and making a Blueprint customization should only be done within the context of the editor, either by wrapping our customization codes in WITH_EDITOR or WITH_EDITORONLY_DATA or by creating an editor only module.

An example of blueprint customization is UWidgetBlueprint of UMG (Unreal Motion Graphics), it is derived from UBlueprint and has its own custom editor that is extended from the common blueprint editor, this custom editor has a designer panel that allows us to design the layout of the widget, it is very convenient compared to creating UI by code using Slate, especially for non programmers, it speeds up the UI development process significantly.

widget-blueprint

UWidgetBlueprint, no matter how different it is from ActorBlueprint or AnimationBlueprint, is basically doing the same thing, it creates a Class that extends its ParentClass to produce a new Class. The many extensions that has been done is just to empower UI programmers and designers in creating game user interface, in a sense, customizing a blueprint means we are creating a custom tool for our game production.

What are the Data?

We already know that the input of a Blueprint is a ParentClass, and the output is a BlueprintGeneratedClass. In producing the output, Blueprint processes a lot of Data inside of it, but before we are going inside a Blueprint you will need to redefine the term ‘Blueprint’ itself, from end-user perspective everything in a Blueprint is a Blueprint, the most common misconception is Blueprint Graph, most developers I know will say that a Blueprint Graph is a Blueprint, e.g: “Hey that’s a cool Blueprint, it looks so tidy, the lines are perfectly aligned and the comments are very descriptive, I like it.”, using the word Blueprint for Blueprint Graph will hinder your understanding of Blueprint. Blueprint is an Object that contains many data, including various Blueprint Graphs to produce a BlueprintGeneratedClass, that’s it!

So, What are the data? here they are:

Skeleton Object and Class Default Object

cdo

First of all Blueprint will generate a BlueprintGeneratedClass that is derived from the ParentClass, and then it creates two default objects for this generated class, one of them is a skeleton object (note: it has nothing to do with skeletal mesh), and the other one is the actual default object that will be use as the class default object of the generated class. If you edit an inherited property from the parent class in blueprint editor then you are actually editing the class default object, and if you revert the value that you have edited, then you are reverting it to its skeleton property value.

List of New Properties

vars

The second data in Blueprint is a list of new properties, when you add a new variable in Blueprint it will be added to this list. The mechanism of this property list is actually pretty complex that it needs its own article, so for this article we just assume that there is a property list that records new properties that we create in blueprint.

Simple Construction Script

scs

The third one is a Simple Construction Script (SCS), it is a tree that contains components to be instantiated when an object of this class is created, you can only see the tree when you are creating an actor blueprint, in the editor this is called components tree.

Blueprint Graphs

Graphs

The last one are various Blueprint Graphs, the correct technical term for this is Editor Graph (UEdGraph), there are four categories of Graphs in a common Blueprint: Event Graphs, Function Graphs, Macro Graphs and DelegateSignatureGraph (Event Dispatchers); If you have ever created a blueprint in the editor, then you should already know what they are just by looking at the categories on the left side of the graph editor. We can create more than one event graphs, but in the end they will all be collected into a single Graph that is called an UberGraph (you have probably heard of it when you have error in your blueprint graph). So, what are these graphs? they are basically source codes in the form of a graph that will be compiled into byte codes that can then be fed into UnrealScript virtual machine.

How Does It Generates Its Output?

To generate a BlueprintGeneratedClass, Blueprint needs to be compiled, the compilation process is done by FKismetCompilerContext that is created every time a blueprint is about to be compiled.

Epic has made a good documentation on how this compiler works, you can read it here:

https://docs.unrealengine.com/latest/INT/Engine/Blueprints/TechnicalGuide/Compiler/

Summary

This is the end of this short article about what is inside an Unreal Engine Blueprint.

I hope this article can help you start your own journey in understanding and creating your own blueprint extensions that can help you optimize and speeds up your game production process and creating useful tools for your game development team.

Thanks for reading and please let me know if I have made mistakes in my article.

UObject Constructor, PostInitProperties and PostLoad

Unlike the common c++ constructor, Unreal Engine 4 has a lot of things going on while it creates or loads an object. And in this post I am going to explore the three functions related to object creation: Constructor, PostInitProperties, and PostLoad.

This post is a part of my Unreal Engine study, the goal is not to modify or tweak the engine but to make me better at deciding where I should write a particular object initialization code in the game. I assume you already have at least a bit of understanding and experience in writing Unreal Engine c++ codes and have generally known the unreal engine tool chain (UHT and UBT).

Change of Paradigm

UObject is the base of almost all of Unreal Engine objects, including UProperties, UStruct, UClass, UActor, etc. When writing a c++ class sometime we need to initialize some properties that we have made, for example:

class MyClass
{
	int32 X;
	int32 Y;
public:
	CFoo( int32 InX, int32 InY )
    	: X(InX)
    	, Y(InY)
	{}
};

And then we do the following to create an object of that class:

MyClass A = new MyClass( 10, 10 );

It is pretty standard, and we probably use it all the time in c++ but alas we can not do it like that for UObject class, it is inconvenient at first, especially when you’re used to it before you are using Unreal Engine, but all we need to do is to change our paradigm, Unreal Engine has so many cool features such as object replication, reflection, object garbage collection, etc. You only need to adapt to the special way in which Unreal Engine does its things, the trade off between convenience and benefits are very significant, especially if we broaden our view to the whole game production, it empowers the whole team, not just programmers, we can implement cool game features that are easy to tweak, we can create our own game system based on what Unreal Engine has provided and create a custom editor for it, and many more. If you do not change your paradigm and insist to use the way you are convenient with before you use Unreal Engine then you will have a hard time in your game development.

One of my friend insisted that he wanted to use a full non-unreal engine c++ to create item and inventory system for his game just because he had done something similar in his previous game and he did not want to change his way of doing things, what happened next was he spent weeks implementing it, I admit it was a solid system from native c++ perspective but it was so hard to integrate it to Unreal Editor, he needed to make his own serialization code, he needed to make his own item editor from scratch, he needed to expose his non-unreal objects to actors in the world, it was just too hard to do and he gave up midway, he missed the point of using Unreal Engine to help us game programmers to implements our features easily.

All we need to do is to accept it as it is and just climb the steep learning curve of Unreal Engine c++ programming and we will reap the great benefit of increased productivity and efficiency later.

Methodology

Now back to the topic, this particular blog post is my attempt to understand what UObject Constructor, PostInitProperties, and PostLoad are. The method I am using is to write object information logs whenever these functions are called by Unreal Engine. The information are: Object Path, Object Flags, Class Flags and the value of a custom integer property: Foo.

All Unreal object has a unique path in the form of a string, for example:

/Game/MyGame/MyAsset.MyAsset.ASubObjectOfMyAsset.AnotherObject

If you split the path using dot as delimiter you will get:

1. /Game/MyGame/MyAsset
2. MyAsset
3. ASubObjectOfMyAsset
4. AnotherObject

Each of them represents different objects where the later object is contained within the previous object, in Unreal Engine term: the later object has the previous object as its outer. The outer-most object is always a special object called Package, in this case it is /Game/MyGame/MyAsset, and all Unreal Engine object except for Package always directly or indirectly contained within a Package.

Object flags is a bit flags that tells us the state of the object, for example if it has RF_Public then this object is visible outside of its package.

Class flags is a bit flags of the object’s class, for example, if it has CLASS_Abstract then the class can not be instantiated. Class itself is a UObject that has UStruct as its parent, but I am not going to delve into it this time as it deserves its own study.

For the purpose of the test I created an object class, UTestObject :

UCLASS(Blueprintable)
class PACZ_API UTestObject : public UDataAsset
{
    GENERATED_BODY()
public:

	/** Custom Property, Foo. */
	UPROPERTY( EditAnywhere, BlueprintReadWrite, Category = "Test" )
	int32 Foo = 100;

public:

	/** Constructor. */
	UTestObject(const FObjectInitializer& ObjectInitializer);

	/** PostInitProperties override. */
	virtual void PostInitProperties() override;

	/** PostLoad override. */
	virtual void PostLoad() override;
};

I put my logging codes in all of the three functions: UTestObject (the constructor), PostInitProperties and PostLoad; I will then examine the logs that are written whenever these functions are called.

Pacz is the primary game module that I use to do the test, thus PACZ_API is the API keyword for this module, unless you are certain that you want to keep this class private within its own module then it is a good practice to add the API keyword (or MinimalAPI class flag) to your class, because you never know whether you want to expose it later along the development, I will not discuss this any further because module management is a big subject that has already been clearly documented in Unreal Engine learning resources.

ClassDefaultObject

After I have written my UTestObject in c++, I started up the editor, and it triggered the first construction of my test object, the logs are as follows:

[Constructor]
     Object Path  = /Script/Pacz.Default__TestObject
     Object Flags = Public ClassDefaultObject ArchetypeObject
     Class Flags  = Native RequiredAPI Intrinsic Constructed
     Foo          = 100
[PostInitProperties]
     Object Path  = /Script/Pacz.Default__TestObject
     Object Flags = Public ClassDefaultObject ArchetypeObject
     Class Flags  = Native RequiredAPI Intrinsic Constructed
     Foo          = 100

The object constructed by Unreal Engine was the ClassDefaultObject, every class has at least one default object, it is an ArchetypeObject which means that it is an object that can act as a template for another object instantiated from this class.

Now please examine the package of this object, it is in /Script/(ModuleName), in my case it is /Script/Pacz, your native unreal objects (including classes) in a certain module will all be contained in this package, it is populated by Unreal Header Tool (UHT) whenever you compile your c++ code. If you have another game module in your project, for example MyGameEditor, then all native unreal objects in that module will resides in /Script/MyGameEditor. Please note that all c++ codes that are not marked by special UHT macros (e.g: UENUM, UCLASS, UFUNCTION etc) will not be visible to Unreal Engine, it will not even know that these functions, classes, or properties even exist in the first place.

The object flag Public (RF_Public), means that this object is visible outside of its package, an example of non public object is a sub object, you need to actually get the instance of its outer and then access the object. Every object you can see or use in the editor without opening a special editor for a certain object (e.g Blueprint Editor, UMG Editor, etc) is Public.

Now lets see the Class Flags, the class is marked as Native, which means it’s from native c++ code instead of from Blueprint (Blueprint generates non-native object class), it is also marked as RequiredAPI, this is the result of adding PACS_API when I wrote the class in c++, if I was to omit the API keyword then it will not be marked as such.

The last class flag is Constructed, all native c++ object classes will be marked as constructed, only blueprint generated classes have the possibilities of not being marked with this flag when those classes have not been constructed by the blueprint construction system.

The last line in the log shows the value of Foo, the value is 100 because this is what I have specified in c++, we will later drr how it will change when we create an asset of this class.

If you are meticulous enough you should have already noticed that PostLoad was not called in this phase, that’s because native objects does not need to be loaded, or we can say that they have already been loaded when the dynamic library in which they reside is loaded by Module Manager.

UTestObject as Asset

Because UTestObject is derived from UDataAsset, it can be instantiated as an asset in the editor, so I go ahead and make an asset of it and I named it MyTestObject and this is the log:

[Constructor]
     Object Path  = /Game/MyTestObject.MyTestObject
     Object Flags = Public Standalone Transactional
     Class Flags  = Native RequiredAPI TokenStreamAssembled Intrinsic Constructed
     Foo          = 100
[PostInitProperties]
     Object Path  = /Game/MyTestObject.MyTestObject
     Object Flags = Public Standalone Transactional
     Class Flags  = Native RequiredAPI TokenStreamAssembled Intrinsic Constructed
     Foo          = 100

What has happened here was Unreal Engine created a new package, /Game/MyTestObject, and then it created a new object of class UTestObject, and then the class default object was copied to this new object, it is the reason why the value of Foo for this new object is 100.

Let’s look at the object flags, it’s not the same as the flags of class default object, because they are different, this is an asset object, not an archetype object, this is why it does not have both ClassDefaultObject and Archetype flag anymore.

There are two new flags in this object: Standalone and Transactional.

Standalone means that this object will not be discarded even if it is not referenced by another object, you have probably known that Object will be discarded (or garbage collected) by unreal engine if it is not strongly referenced or it is not rooted (rooting an object is not within the scope of this post so I will not discuss it here), and from this test we also know that objects that are flagged as standalone will not be garbage collected, but the caveat here is that they are not discarded as long as the packages they’re in are loaded, if for some reason the packages are unloaded, these objects will be elligible to be garbage collected;

Transactional means that almost all changes to the value of the properties of this object are recorded and can be reverted, which means we can undo or redo the changes in the Editor.

In the log, you can see that the UTestObject class gains a new flag, TokenStreamAssembled, this means that the token stream of this class has been assembled and ready to be used by others (Kismet blueprint nodes, details panel, property widgets, etc), Unreal Engine assembles the token stream before hand because the user needs it to edit the asset. I am not particularly sure about this but I assume this is what had happened based on my limited understanding of Unreal Engine.

Editing Foo

I opened up the asset by double clicking it, it opened up an object editor, and then I changes the value of Foo to 25 and save the asset.

There is nothing printed in the log, which means none of the three functions are called, but what happened here was I directly edited the property Foo and the package in which the object is contained is marked as dirty (it is displayed as asterisk character at the bottom left of the asset’s thumbnail), and then when I saved it the asset object was serialized to disk and the asterisk character was gone (because it was not dirty anymore).

Post Load

So, when does the PostLoad function gets called by Unreal Engine? for this we need to restart the editor in order to force the asset to be reloaded (there are other ways to do this but this is the simplest one and the test project is small enough that restarting it only takes a few seconds).

After I restarted the editor, there is no PostLoad for the new asset, why? because Unreal Engine should not do that, all assets are in the form of meta data (FDataAsset) when the editor starts, the actual assets are loaded only when they are actually used, let’s imagine a project that has gigabytes of assets, if Unreal were to load them when the editor starts, they will take tremendous amount of time and memory space and I am not sure if the PC we’re using is able to handle such huge amount of data.

To trigger PostLoad, we need to use the asset, so I just opened it in the editor and this is the log:

[Constructor]
     Object Path  = /Game/MyTestObject.MyTestObject
     Object Flags = Public Standalone Transactional NeedLoad NeedPostLoad NeedPostLoadSubObjects WasLoaded
     Class Flags  = Native RequiredAPI TokenStreamAssembled Intrinsic Constructed
     Foo          = 100
[PostInitProperties]
     Object Path  = /Game/MyTestObject.MyTestObject
     Object Flags = Public Standalone Transactional NeedLoad NeedPostLoad NeedPostLoadSubObjects WasLoaded
     Class Flags  = Native RequiredAPI TokenStreamAssembled Intrinsic Constructed
     Foo          = 100
[PostLoad]
     Object Path  = /Game/MyTestObject.MyTestObject
     Object Flags = Public Standalone Transactional WasLoaded LoadCompleted
     Class Flags  = Native RequiredAPI TokenStreamAssembled Intrinsic Constructed
     Foo          = 25

As you can see here, in PostInitProperties, the value of Foo is still the same as the one from ClassDefaultObject, 100, only after the object has been loaded will it change to the value we have previously entered, 25. You have probably known that we can revert the value of a certain properties by clicking the yellow rollback arrow at the end of the property value, reverting a value means that the value is reverted back to the archetype object value.

Conclusion

This is the end of the simple test that I have conducted, there are many interesting things that I have learned during the test but I did not write in this post because I want to keep it short (because it’s just a blog post, not a book).

I also realized that I haven’t explained the difference between Constructor and PostInitProperties, although they looked the same but they are actually two very different things, to put it simply in Constructor the object is still an abstract entity, it can not see the “world” yet, it’s still in incubation, while in PostInitProperties the object has been born, it has gotten out of its womb and ready to go on an adventure. There are a lot of things you can do in the constructor that can not be done in PostInitProperties and vice versa.

I have actually done a lot of other similar test for many kinds of objects, the most interesting one is when I examined an actor blueprint using this method, I learned how both the skeleton object and the generated class default object of the blueprint were constructed and loaded, I also learned the difference between object flags and class flags for different object instances in the blueprint. What happened under the hood when the actor blueprint was spawned into the world really helped me to both understand more about Unreal Engine and helped me implemented a particular feature in the game that i am currently making.

Some of you may think that it is unnecessary to know these kind of things and to just use blueprint for everything, it’s probably true for small game projects or a project that only uses the existing Gameplay classes that Unreal Engine has provided (they are mostly related to multiplayer game using a set of built-in character archetypes) but what if you wanted to make an original gameplay that is different from what has been provided by Unreal Engine? Let’s say you are creating something like Civilization or Skyrim, what will you do then? you will inevitably need to know this stuff, and it’s not an easy thing to learn, at least for me, learning it as early as possible is the best way to do to prepare for the problems we are going to face later in our project (or future projects).

Thank you for reading this post and I will be very happy and grateful if you can spot any errors in my understanding of Unreal Engine and tell me all about it in the comment section or e-mail.