---
title: Unreal Engine tips and tricks
tags: engine
description: Unreal Engine tips and tricks
breaks: false
---
<style>.markdown-body { max-width: 1200px; }</style>
<!-- {%hackmd theme-dark %} -->
# Unreal Engine
[TOC]
# Paths
## Windows
- https://nerivec.github.io/old-ue4-wiki/pages/packaged-game-paths-obtain-directories-based-on-executable-location.html
**Shipping**:
```
c:\Users\%USERNAME%\AppData\Local\<Project Name>\Saved\
```
## Mac
**Config:**
```
~/Library/Preferences/Unreal Engine/
~/Library/Preferences/<packaged project name>/
```
**Logs:**
```
~/Library/Logs/Unreal Engine/
~/Library/Logs/<packaged project name>/
```
**Save games/Rest:**
```
~/Library/Application Support/Epic/
```
**Crashes:**
```
~/Library/Application Support/Epic/UnrealEngine/<Engine Version>/Saved/Crashes
```
# [Advanced Debugging in Unreal Engine](https://dev.epicgames.com/community/learning/tutorials/dXl5/advanced-debugging-in-unreal-engine)
# USTRUCT/UCLASS/UFUNCTION/UPARAM/UPROPERTY
- [USTRUCT](https://benui.ca/unreal/ustruct/)
- [UCLASS](https://benui.ca/unreal/uclass/)
- [UFUNCTION](https://benui.ca/unreal/ufunction/)
- [UPARAM](https://benui.ca/unreal/uparam/)
- [UPROPERTY](https://benui.ca/unreal/uproperty/)
# [UMG](https://docs.unrealengine.com/en-US/Engine/UMG/index.html)
Resourcces:
- http://benhumphreys.ca/unreal/
- [A Compendium Information Guide for UMG and Slate in Unreal Engine.](https://github.com/YawLighthouse/UMG-Slate-Compendium#table-of-contents)
# [GPU](https://docs.unrealengine.com/en-US/Engine/Performance/GPU)
# [CPU](https://docs.unrealengine.com/en-us/Engine/Performance/CPU)
# [Configuration Files](https://docs.unrealengine.com/en-US/Programming/Basics/ConfigurationFiles/#filehierarchy)
The configuration file hierarchy is read in starting with `Base.ini`, with values
in later files in the hierarchy overriding earlier values. All files in the Engine
folder will be applied to all projects, while project-specific settings should be
in files in the project directory.
Finally, all project-specific and platform-specific differences are saved out to `[ProjectDirectory]/Saved/Config/[Platform]/[Category].ini`
The below file hierarchy example is for the Engine category of configuration files.
1. `Engine/Config/Base.ini`
Base.ini is usually empty.
2. `Engine/Config/BaseEngine.ini`
3. `Engine/Config/[Platform]/[Platform]Engine.ini`
4. `[ProjectDirectory]/Config/DefaultEngine.ini`
5. `[ProjectDirectory]/Config/[Platform]/[Platform]Engine.ini`
6. `[ProjectDirectory]/Saved/Config/[Platform]/Engine.ini`
The configuration file in the Saved directory only stores the project-specific
and platform-specific differences in the stack of configuration files.
## Complete hierarchy
```cpp
// Possible entries in a config hierarchy
enum class EConfigFileHierarchy : uint8
{
// Engine/Config/Base.ini
AbsoluteBase = 0,
// Engine/Config/*.ini
EngineDirBase,
// Engine/Config/Platform/BasePlatform* ini
EngineDir_BasePlatformParent,
EngineDir_BasePlatform,
// Engine/Config/NotForLicensees/*.ini
EngineDirBase_NotForLicensees,
// Engine/Config/NoRedist/*.ini -Not supported at this time.
EngineDirBase_NoRedist,
// Game/Config/*.ini
GameDirDefault,
// Game/Config/DedicatedServer*.ini
GameDirDedicatedServer,
// Game/Config/NotForLicensees/*.ini
GameDirDefault_NotForLicensees,
// Game/Config/NoRedist*.ini
GameDirDefault_NoRedist,
// Engine/Config/PlatformName/PlatformName*.ini
EngineDir_PlatformParent,
EngineDir_Platform,
// Engine/Config/NotForLicensees/PlatformName/PlatformName*.ini
EngineDir_PlatformParent_NotForLicensees,
EngineDir_Platform_NotForLicensees,
// Engine/Config/NoRedist/PlatformName/PlatformName*.ini
EngineDir_PlatformParent_NoRedist,
EngineDir_Platform_NoRedist,
// Game/Config/PlatformName/PlatformName*.ini
GameDir_PlatformParent,
GameDir_Platform,
// Game/Config/NotForLicensees/PlatformName/PlatformName*.ini
GameDir_PlatformParent_NotForLicensees,
GameDir_Platform_NotForLicensees,
// Game/Config/NoRedist/PlatformName/PlatformName*.ini
GameDir_PlatformParent_NoRedist,
GameDir_Platform_NoRedist,
// <UserSettingsDir|AppData>/Unreal Engine/Engine/Config/User*.ini
UserSettingsDir_EngineDir_User,
// <UserDir|Documents>/Unreal Engine/Engine/Config/User*.ini
UserDir_User,
// Game/Config/User*.ini
GameDir_User,
// Number of config files in hierarchy.
NumHierarchyFiles,
};
```
# [In game console commands](https://digilander.libero.it/ZioYuri78/)
What is a Console Variable? [See Docs](https://docs.unrealengine.com/en-US/Programming/Development/Tools/ConsoleManager/#whatisaconsolevariable?)
## [Priority](https://docs.unrealengine.com/en-US/API/Runtime/Core/HAL/EConsoleVariableFlags/index.html)
Priority for console commands from lower to higher goes like this:
1. [`SetByConstructor`](#constructor) - When created, default
2. [`SetByScalability`](#Scalability-Config) - From `Scalability.ini` (lower priority than game settings so it's easier to override partially)
3. [`SetByGameSetting`](#Game-Settings) - This is usually set from your Game Settings In Game UI or from a file
4. [`SetByProjectSetting`](#Project-Settings) - Project settings (editor UI or from file, higher priority than game setting to allow to enforce some setting for this project)
5. [`SetByDeviceProfile`](#Device-Profiles) - Per device setting in `DeviceProfiles.ini` (e.g. specific iOS device, higher priority than per project to do device specific settings).
6. [`SetByConsoleVariablesIni`](#Console-Variables-Config) - `Consolevariables.ini` (for multiple projects) set in `Engine/Config`
7. [`SetByCommandline`](#Command-Line) - A minus command e.g. -VSync (very high priority to enforce the setting for the application)
8. [`SetByCode`](#Code) - Least useful, likely a hack, maybe better to find the correct SetBy...
9. [`SetByConsole`](#Console) - Editor UI or console in game or editor
## Constructor
See [Creating / Registering a Console Variable](https://docs.unrealengine.com/en-US/Programming/Development/Tools/ConsoleManager/#creating/registeringaconsolevariable)
Basically `ECVF_SetByConstructor === ECVF_Default`.
Example:
```cpp
static TAutoConsoleVariable<int32> CVarNormalMaps(
TEXT("r.NormalMapsForStaticLighting"),
0,
TEXT("Whether to allow any static lighting to use normal maps for lighting computations."),
ECVF_Default
);
```
## Scalability Config
From `Scalability.ini` (lower priority than game settings so it’s easier to override partially).
Example:
```ini
[ViewDistanceQuality@0]
r.SkeletalMeshLODBias=2
r.ViewDistanceScale=0.4
[ViewDistanceQuality@1]
r.SkeletalMeshLODBias=1
r.ViewDistanceScale=0.6
```
## Game Settings
This is usually set from your Game Settings In Game UI or from a file.
The config is usually kept inside `GameUserSettings.ini` and see the contents of `UGameUserSettings`.
Examples of console variables that might be set by the game user settings:
```ini
r.FullScreenMode
r.VSync
r.HDR.EnableHDROutput
```
## Project Settings
## Console Variables Config
NOTE: Engine Only
## Command Line
## Code
## Device Profiles
These console commands can be set in the `DeviceProfiles.ini` file.
Example:
```ini
[Android DeviceProfile]
DeviceType=Android
BaseProfileName=
+CVars=r.MobileContentScaleFactor=1
+CVars=r.BloomQuality=0
+CVars=r.DepthOfFieldQuality=0
+CVars=r.LightShaftQuality=0
+CVars=r.RefractionQuality=0
+CVars=r.ShadowQuality=2
+CVars=slate.AbsoluteIndices=1
+CVars=r.Vulkan.DelayAcquireBackBuffer=0
+CVars=r.Vulkan.RobustBufferAccess=1
+CVars=r.Vulkan.DescriptorSetLayoutMode=2
```
## Console
`` (back tick) ` `` - Open the developer console.
This is the highest priority you can set for commands.
```markdown
# View modes
viewmode <mode>
// Where <mode> can be:
BrushWireframe - wireframes with brushes (crashes at runtime)
Wireframe - wireframes with BSP (crashes at runtime)
Unlit - unlit
Lit - lit
Lit_DetailLighting - lit + detaillighting
LightingOnly - lit without materials
LightComplexity - colored according to light count
ShaderComplexity - colored according to shader complexity
LightmapDensity - colored according to world-space LightMap texture density
// Colored according to light count
LitLightmapDensity
ReflectionOverride
VisualizeBuffer
StationaryLightOverlap - Colored according to stationary light overlap
// collision
CollisionPawn
CollisionVisibility
LODColoration - Colored according to the current LOD index
QuadOverdraw - Colored according to the quad coverage
PrimitiveDistanceAccuracy - Visualize the accuracy of the primitive distance
computed for texture streaming
MeshUVDensityAccuracy - Visualize the accuracy of the mesh UV densities
computed for texture streaming
ShaderComplexityWithQuadOverdraw - Colored according to shader complexity, including
quad overdraw
HLODColoration - Colored according to the current HLOD index
GroupLODColoration - Group item for LOD and HLOD coloration
MaterialTextureScaleAccuracy - Visualize the accuracy of the material texture
scales used for texture streaming
RequiredTextureResolution - Compare the required texture resolution to the
actual resolution
ShowFlag.Bones 1 - shows bones of all stuff that has bones
ShowFlag.StationaryLightOverlap 1 - shows the overlap of stationary ligths
ShowFlag.Bounds 1 - shows all bounds
# Debug
debug rendercrash | rendergpf - Crash the renderer
debug rendercheck - Crash the renderthread via check(0) at your request
debug renderensure - Crash by ensure() condition inside the renderer
debug threadcrash - Crash inside worker thread via UE_LOG(Fatal)
debug threadcheck - Crash worker thread via check()
debug threadgpf - Crash worker thread via invalid memomory assigment
debug twothreadcrash - Crash two threads at once via UE_LOG(Fatal)
debug twothreadgpf - Crash two threads at once via invalid memomory assigment
debug threadensure - Crash worker thread via ensure()
debug threadfatal - Crash thread via LowLevelFatalError()
debug crash - Crash game via UE_LOG(Fatal)
debug check - Crash game via check()
debug gpf - Crash game via invalid memomory assigment
debug ensure - Crash game via ensure()
debug fatal - Crash game via LowLevelFatalError()
debug bufferoverrun - Crash via buffer overflow
debug crtinvalid - Crash via invalid cast
debug eatmem - Fills up all your computer memory
debug recurse - Crash via infinite recursion
debug threadrecurse - Crash via infinite recursion in a separate thread
debug stackoverflow - Crash via stack overflow via infinite recursion
debug threadstackoverflow - Crash via stack overflow in a separate thread
debug hitch - Hitch the game for 1 second
debug renderhitch - Hith the render for 1 second
debug softlock - Hands the current thread
debug infiniteloop - Hang the CPU forever (infinite loop)
debug sleep - Sleep for 1 hour. This should crash after a few seconds in cooked builds.
debug audiogpf - Crash auto thread via invalid memomory assigment
debug audiocheck - Crash audio thread via check()
# Choose graphics card
r.GraphicsAdapter - User request to pick a specific graphics adapter (e.g. when using a integrated graphics card with a discrete one)
D3D12.GraphicsAdapter - User request to pick a specific graphics adapter (e.g. when using a integrated graphics card with a discrete one)
# Other
WidgetReflector - opens up the widget reflector (works even in non editor builds)
```
# [Command line arguments](https://docs.unrealengine.com/en-us/Programming/Basics/CommandLineArguments)
- https://benui.ca/unreal/command-line-arguments/
When running the game you can append these arguments:
```bash
-Windowed - run in windowed mode
-FullScreen - run in full screen mode
-ForceRes - force the resolution
-ResX= | -ResY= - set the X and Y resolution
-WinX= | -WinY= - set the position of the game window in X/Y coordinates
-SaveWinPos - saves the window position into the game user settings file
-Seconds - set the maximum tick time
-Verbose - set compiler to use verbose output.
-VerifyGC | -NoVerifyGC - enables/disable garbage collection verification every 30s
-StatNamedEvents - enable named stat events
-LoadTimeStats - enable load time stats, shortcut for some stat gorup commands
-LoadTimeFile - enable load time stats to a file, shortcut for some stat gorup commands
-LogThreadedParticleTicking - log the thread of the particles ticking
-VerifyDDC - verifies the derived data cache (https://docs.unrealengine.com/en-us/Engine/Basics/DerivedDataCache)
-Debug - running in debug
-NoAmbientActors - mute ambient sound actors
-HDR | -NoHDR - enables/disables HDR
-CleanCrashReports - clean the crash reports
-CrashForUAT - write UAT markers on crash
-NotInstalled - similar to NotInstalledEngine
-Installed - similar to InstalledEngine
-NotInstalledEngine - tells it that the engine is not installed
-InstalledEngine - tells that the engine is installed
-WaitForDebugger - if was specified, halt startup and wait for a debugger to attach before continuing
-PromptRemoteDebug - Prompt Remote Debug
-SlateDebug - create slate test windows
-ScriptStackOnWarnings - Show blueprint script stack for warnings, same config in Engine.ini
-EnableSound | -NoSound - enables/disables sound
-VSync | -NoVSync - enables/disables vsync
-OneThread - runs with only one thread instead of multi-threading
-Threading - enables threading
-NoThreading - disables threading
-NoThreadTimeout - stop hang detection
-NoConsole - disables console ouput
-No<OnlineSubsystemName> - disables the <OnlineSubsystemName>
-NoTextureStreaming - disable texture streaming. Highest quality textures are always loaded.
-NoSplash - Disable use of splash image when loading the game.
-CmdLineFile=<cmd.txt> - Only in Non Shipping and Editor. File to give to the executable with command line arguments
-Exec=<exec_file.txt> - Executes the specified exec file.
-ExecCmds="command1; command2;" - Executes deffered commands
-bForceSmokeTests - forces the smoke tests?
-Log - show the log
-Silent - disables output and feedback
-WarningsAsErrors - treat warnings as errors
-ForceLogFlush - force a log flus after each line
-LogTimes - display the log times in UTC format ELogTimes::UTC
-UTCLogTimes - same as LogTimes
-NoLogTimes - disable the log times
-LocalLogTimes - display the log times in local time format ELogTimes::Local
-LogTimeCode - display the log times as timecode
-stdout - Enables the stdout device
-FullStdOutLogOutput - Display all log levels to stdout
-AllowStdOutLogVerbosity = display only ELogVerbosity::Log to stdout
-NoScreenMessage - disables the screen messages
-NoLoadingScreen - disables the PreLoadingScreen on windows in non shipping builds
-NoEpicPortal - disables some parts of the epic games launcher (NOTE does not seem to disable it completly)
-EnableAllPlugins - enables all the plugins
-ExceptPlugins=<comma separated list> - used in conjuction with -EnableAllPlugins
-NoEnginePlugins - disable all the engine plugins
-Benchmark
-FPS=<int> - Used with the benchmark command, fixed delta time
# Curl
-NoReuseConn - don't reuse connections
-NoTimeouts - don't use timeouts I guess
# Linux
-UseHyperThreading - enables the use of hyperthreading on linux
-WaitAndForkRequireResponse - wait for forks (fork())
# Steam
-NoSteam - set steamworks to not be used.
# OpenGl/Vulkan
-OpenglDebug - debug opengl
-Opengl4 - force with opengl 4
-Opengl3 - force with opengl 3
-Opengl - run with opengl
-Vulkan - run with vulkan
# DirectX
-dxdebug | -d3debug | d3ddebug - use a debug device
-d3dbreakonwarning - breaks on warning, debug
-d3d10 | -dx10 | -sm4 - use directx 10 (default is directx 11)
-d3d11 | -dx11 - use directx 11
-d3d12 | -dx12 - use directx 12
-novendordevice - apparently only AMD and directx 11
-AllowSoftwareRendering - allow to use software rendering fallback
-PreferAMD - use AMD card
-PreferIntel - use Intel card
-PreferNvidia - use Nvidia card
```
# [Logs](https://michaeljcole.github.io/wiki.unrealengine.com/Logs,_Printing_Messages_To_Yourself_During_Runtime/)
## [Project logs](https://michaeljcole.github.io/wiki.unrealengine.com/Locating_Project_Logs/)
## [Logging in Shipping Builds](https://stefanperales.com/blog/ue4-quick-tip-logging-in-shipping-builds/)
Used by multiple files:
```cpp
// inside header
DECLARE_LOG_CATEGORY_EXTERN(CategoryName, DefaultVerbosity, CompileTimeVerbosity);
// inside cpp
DEFINE_LOG_CATEGORY(CategoryName);
```
Used in only one file, `static` log:
```cpp
// inside cpp
DEFINE_LOG_CATEGORY_STATIC(CategoryName, DefaultVerbosity, CompileTimeVerbosity);
```
Where:
- `CategoryName` - is simply the name for the new category you are defining.
- `DefaultVerbosity` - is the verbosity level used when one is not specified in the ini files or on the command line. Anything more verbose than this will not be logged.
- `CompileTimeVerbosity` - is the maximum verbosity to compile in the code. Anything more verbose than this will not be compiled.
Examples:
```cpp
// Inside header
DECLARE_LOG_CATEGORY_EXTERN(LogMyGame, All, All);
// inside cpp
DEFINE_LOG_CATEGORY(LogMyGame);
// or static used only inside this cpp file
DEFINE_LOG_CATEGORY_STATIC(LogUsedOnlyInsideCPP, All, All);
```
# JSON
NOTE: There is an issue with this serializer where in editor it converts the field to `Field` but in packaged game it converts the field to `field`.
```cpp
#include "IStructSerializerBackend.h"
#include "StructSerializer.h"
#include "StructDeserializer.h"
#include "Backends/JsonStructDeserializerBackend.h"
#include "Serialization/BufferArchive.h"
#include "Serialization/BufferWriter.h"
#include "Backends/JsonStructSerializerBackend.h"
// Serializes a given USTRUCT to a JSON string using the default policy.
// @return A string holding the serialized object in JSON format
template<typename StructType>
static void SerializeToJSON(const StructType& Struct, FString& OutString)
{
SerializeToJSON(&Struct, *Struct.StaticStruct(), OutString);
}
static void SerializeToJSON(const void* Struct, UStruct& TypeInfo, FString& OutString)
{
// Read into this
FBufferArchive BufferArchive;
// Save to JSON
const EStructSerializerBackendFlags SerializerFlags = EStructSerializerBackendFlags::Default;
FStructSerializerPolicies SerializerPolicies;
FJsonStructSerializerBackend Backend(BufferArchive, SerializerFlags);
FStructSerializer::Serialize(Struct, TypeInfo, Backend, SerializerPolicies);
if (BufferArchive.TotalSize() == 0)
{
return;
}
// Add string terminator
// NOTE: we need two zeros here otherwise the conversion to string will not be right
BufferArchive.Add(0);
BufferArchive.Add(0);
// Convert to String
OutString = FString((TCHAR*)BufferArchive.GetData());
}
// Deserializes a given JSON String into a specific struct
// @return true if it could deserialize the json string into the struct
template<typename StructType>
static bool DeserializeFromJSON(const FString& JSONString, StructType& OutStruct)
{
return DeserializeFromJSON(JSONString, &OutStruct, *StructType::StaticStruct());
}
static bool DeserializeFromJSON(const FString& JSONString, void* OutStruct, UStruct& TypeInfo)
{
// Read from this
const bool bInFreeOnClose = false;
const bool bIsPersistent = false;
FBufferReader BufferReader((void*)*JSONString, JSONString.Len() * sizeof(TCHAR), bInFreeOnClose, bIsPersistent);
// Load from JSON
FJsonStructDeserializerBackend Backend(BufferReader);
FStructDeserializerPolicies DeserializerPolicies;
DeserializerPolicies.MissingFields = EStructDeserializerErrorPolicies::Warning;
return FStructDeserializer::Deserialize(OutStruct, TypeInfo, Backend, DeserializerPolicies);
}
```
# [Performance and profiling](https://docs.unrealengine.com/en-us/Engine/Performance)
Resources:
- https://docs.unrealengine.com/en-us/Engine/Performance
>>>
NOTE: that enabling any stats for live viewing affects the game thread performance
>>>
## [Stat commands](https://docs.unrealengine.com/en-us/Engine/Performance/StatCommands)
>>>
NOTE: To open the `*.ue4stats` file use the [SessionFrontend Profiler Tab](https://docs.unrealengine.com/en-US/Engine/Performance/Profiler/index.html)
>>>
```
stat <Category>
// Most useful categories
stat Unit - Overall frame time as well as the game thread, rendering thread, and GPU times.
stat UnitGraph - To see a graph with the stat unit data
// But to start/stop recording in packaged game
// The stats file is located inide [UE4ProjectFolder]\[ProjectName]\Saved\Profiling\UnrealStats.
// Open the *.ue4stats file with the SessionFrontend from unreal.
stat StartFile - Starts a statistics capture, creating a new file in the Profiling directory.
stat StopFile - Finishes statistics capture that was started by the stat StartFile command, closing the file that was created in the Profiling directory.
```
### Memory profiling
https://pzurita.wordpress.com/2015/02/10/limitations-of-memory-tracking-features-in-unreal-engine-4/
### Adding own stat categories in C++
See whole docs in [`Runtime/Core/Public/Stats/Stats.h`](https://github.com/EpicGames/UnrealEngine/blob/release/Engine/Source/Runtime/Core/Public/Stats/Stats.h)
Stats system in the UE4 supports following stats types:
- `Cycle Counter` - a generic cycle counter used to counting the number of cycles during the lifetime of the object
- `Float/Dword Counter` - a counter that is cleared every frame
- `Float/Dword Accumulator` - a counter that is not cleared every frame, persistent stat, but it can be reset
- `Memory` - a special type of counter that is optimized for memory tracking
Each stat needs to be grouped, this usually corresponds with displaying the specified stat group i.e. 'stat statsystem' which displays stats' related data.
To define a stat group you need to use one of the following methods:
- `DECLARE_STATS_GROUP(GroupDesc, GroupId, GroupCat)` - declares a stats group which is enabled by default
- `DECLARE_STATS_GROUP_VERBOSE(GroupDesc, GroupId ,GroupCat)` - declares a stats group which is disabled by default
- `DECLARE_STATS_GROUP_MAYBE_COMPILED_OUT(GroupDesc, GroupId, GroupCat)` - declares a stats group which is disabled by default and may be stripped by the compiler
where
- `GroupDesc` is a text description of the group
- `GroupId` is an UNIQUE id of the group
- `GroupCat` is reserved for future use
- `CompileIn` if set to true, the compiler may strip it out
Example:
```cpp
DECLARE_STATS_GROUP(TEXT("Threading"), STATGROUP_Threading, STATCAT_Advanced);
```
Now, you can declare/define a stat.
A stat can be used only in one cpp file, in the function scope, in the module scope or can be used in the whole project.
For one file scope you need to use one of the following methods depending on the stat type.
- `DECLARE_CYCLE_STAT(CounterName, StatId, GroupId)` - declares a cycle counter stat
- `DECLARE_SCOPE_CYCLE_COUNTER(CounterName, StatId, GroupId)` - declares a cycle counter stat and uses it at the same time, it is limited to one function scope
- `QUICK_SCOPE_CYCLE_COUNTER(StatId)` - declares a cycle counter stat that will belong to stat group called 'Quick'
where
- `CounterName` is a text description of the stat
- `StatId` is an UNIQUE id of the stat
- `GroupId` is an id of the group that the stat will belong to, the GroupId from DECLARE_STATS_GROUP*
- `Pool` is a platform specific memory pool, more details later
- `API` is the *_API of module, can be empty if the stat will be used only in that module
Example:
```cpp
// Declare the stat grup in the header of the file or at the top of the cpp file
DECLARE_STATS_GROUP(TEXT("Threading"), STATGROUP_Threading, STATCAT_Advanced);
// You can declare the stat counter at the top of the file as the category like this
DECLARE_CYCLE_STAT(TEXT("Threading Test"), STAT_ThreadingTest, STATGROUP_Threading);
// In the cpp file
Class::Method()
{
SCOPE_CYCLE_COUNTER(STAT_ThreadingTest);
// OR
// You can declare and use in the same function with
DECLARE_SCOPE_CYCLE_COUNTER(TEXT("Threading Test"), STAT_ThreadingTest, STATGROUP_Threading);
}
```
# Debugging
## Useful development
`` (back tick) ` `` - Open the developer console.
` (apostrophe) ' ` - Open the gameplay debugger
` F1 - F5 ` - change different view modes
Open the WidgetReflector - type in the developer console `WidgetReflector`
## Blueprints
- `FFrame::KismetExecutionMessage`
- `FMessageLog`
- `FBlueprintCoreDelegates::ThrowScriptException`
- `FScriptStackTracker`
## C++
- `FStackTracker`
- `FDebug::DumpStackTraceToLog(VerbosityLevel)`
## Crashes
NOTE: To create a fake crash, type this into the console in game: `debug crash`
NOTE: To force log callstacks you can add `-ForceLogCallstacks` to the command line.
Steps:
1. Go to `Saved/Crashes/<Crash Folder>`
2. You can ignore the log file from the `Crashes` folder as it is not complete, check instead `Saved/Logs/<Log file>` this will have the call stack at the end.
3. Open the project in Visual Studio then open the `UE4Minidump.dmp` file.
4. Start debugging it via clicking on `Debug with Native Only`
## .dmp files
NOTE: if you built the pdb file in another day than the exe was built, use this tool
https://web.archive.org/web/20210205095232/https://www.debuginfo.com/tools/chkmatch.html
```
chkmatch -c .\Game-Win64-Shipping.exe .\Game-Win64-Shipping.pdb
chkmatch -m .\Game-Win64-Shipping.exe .\Game-Win64-Shipping.pdb
```
### Visual studio
1. Open the .dmp file inside VS
2. ![](https://i.imgur.com/eNqmRgt.png)
Set the pdb/exe file path.
3. Run the file
### WinDBG
- https://docs.microsoft.com/en-us/visualstudio/profiling/how-to-specify-symbol-file-locations-from-the-command-line?view=vs-2017
- https://stackoverflow.com/questions/30019889/how-to-set-up-symbols-in-windbg
1. Open the .dmp file inside VS
2. Add the the debug files to the sympath
`.sympath+ c:\dev\illuvium\game-client\Packaged\RELEASE-Illuvium-PrivateBeta1-Win_24_May_2022\Illuvium\Binaries\Win64\`
3. `.reload`
# Customize Structs
- [Custom Struct Serialization for Networking in Unreal Engine](http://www.aclockworkberry.com/custom-struct-serialization-for-networking-in-unreal-engine/)
From `Runtime/CoreUObject/Private/UObject/Class.cpp`
```cpp
// sample of how to customize structs
USTRUCT()
struct ENGINE_API FTestStruct
{
GENERATED_USTRUCT_BODY()
TMap<int32, double> Doubles;
FTestStruct()
{
Doubles.Add(1, 1.5);
Doubles.Add(2, 2.5);
}
void AddStructReferencedObjects(class FReferenceCollector& Collector) const
{
Collector.AddReferencedObject(AActor::StaticClass());
}
bool Serialize(FArchive& Ar)
{
Ar << Doubles;
return true;
}
bool operator==(FTestStruct const& Other) const
{
if (Doubles.Num() != Other.Doubles.Num())
{
return false;
}
for (TMap<int32, double>::TConstIterator It(Doubles); It; ++It)
{
double const* OtherVal = Other.Doubles.Find(It.Key());
if (!OtherVal || *OtherVal != It.Value() )
{
return false;
}
}
return true;
}
bool Identical(FTestStruct const& Other, uint32 PortFlags) const
{
return (*this) == Other;
}
void operator=(FTestStruct const& Other)
{
Doubles.Empty(Other.Doubles.Num());
for (TMap<int32, double>::TConstIterator It(Other.Doubles); It; ++It)
{
Doubles.Add(It.Key(), It.Value());
}
}
bool ExportTextItem(FString& ValueStr, FTestStruct const& DefaultValue, UObject* Parent, int32 PortFlags, UObject* ExportRootScope) const
{
ValueStr += TEXT("(");
for (TMap<int32, double>::TConstIterator It(Doubles); It; ++It)
{
ValueStr += FString::Printf( TEXT("(%d,%f)"),It.Key(), It.Value());
}
ValueStr += TEXT(")");
return true;
}
bool ImportTextItem( const TCHAR*& Buffer, int32 PortFlags, UObject* Parent, FOutputDevice* ErrorText )
{
check(*Buffer == TEXT('('));
Buffer++;
Doubles.Empty();
while (1)
{
const TCHAR* Start = Buffer;
while (*Buffer && *Buffer != TEXT(','))
{
if (*Buffer == TEXT(')'))
{
break;
}
Buffer++;
}
if (*Buffer == TEXT(')'))
{
break;
}
int32 Key = FCString::Atoi(Start);
if (*Buffer)
{
Buffer++;
}
Start = Buffer;
while (*Buffer && *Buffer != TEXT(')'))
{
Buffer++;
}
double Value = FCString::Atod(Start);
if (*Buffer)
{
Buffer++;
}
Doubles.Add(Key, Value);
}
if (*Buffer)
{
Buffer++;
}
return true;
}
bool SerializeFromMismatchedTag(struct FPropertyTag const& Tag, FArchive& Ar)
{
// no example of this provided, doesn't make sense
return false;
}
};
template<>
struct TStructOpsTypeTraits<FTestStruct> : public TStructOpsTypeTraitsBase2<FTestStruct>
{
enum
{
WithZeroConstructor = true,
WithSerializer = true,
WithPostSerialize = true,
WithCopy = true,
WithIdenticalViaEquality = true,
//WithIdentical = true,
WithExportTextItem = true,
WithImportTextItem = true,
WithAddStructReferencedObjects = true,
WithSerializeFromMismatchedTag = true,
};
};
```