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 :
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;lt;FName&amp;amp;gt; PropertyNames; PropertyNames.Add( &amp;amp;quot;Foo&amp;amp;quot; ); PropertyNames.Add( &amp;amp;quot;Bar&amp;amp;quot; ); TraceObject( MyObject, TEXT(&amp;amp;quot;Just another test&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;gt;Actor-&amp;amp;gt;Info-&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.