Some technical notes and related materials on UE4 and VR development that I’ve casually written down, previously scattered around imzlp.com/notes. Today, I’ve organized them, and future notes will be added to this article.
Engine Documents
UE4 Online Documents
- Unreal Engine API Reference
- Coding Standard
- Unreal Architecture
- Gameplay Framework
- Compiling Game Projects
- Asynchronous Asset Loading
- Online Subsystem Overview
- Start Commands
- Command-Line Arguments
- UPARAM
- UPROPERTY
- UFUNCTION
UE GamePlay Framework Tutorial
- Unreal Engine Gameplay Framework Primer for C++
- Gameplay Classes
- Gameplay Programming
- Actor Lifecycle
- This post in Russian (Unofficial)
VR Devices
UE Adaptation to Different VR Devices’ Height Issues
When adapting UE for Oculus Rift and HTC Vive, make sure to change TrackingOrigin
(EHMDTrackingOrigin::Type) to Floor
. Otherwise, the default tracking origin is at eye level, causing the headset height to be incorrect in the game scene.
Another issue to be aware of is that when placing with PlayerStart
, PlayerStart
has a height, which may lead to incorrect height (depending on how your Pawn is written). A solution is to override AGameModeBase
‘s SpawnDefaultPawnAtTransform
to specify the height.
VR Headset Initialization When Starting UE
1 | Stereo On/Off |
Resetting VR Headset Rotation and Position
Since the default orientation of the VR headset along the X-axis is related to the room’s setup, if we start off misaligned with the intended orientation during setup, entering the game will cause it to deviate from what we want the player to see. Therefore, adjustments are needed.
You can use the following function:
1 | /** |
There is also a node with the same name in Blueprints.
Using Oculus Rift in UE
After installing the Oculus Rift device, you need to enable Unknown Source
in the Oculus Store; otherwise, it cannot be previewed in UE.
The relevant page in Unreal’s documentation for adapting Oculus Rift: Developing for Oculus Rift.
Oculus official key operation introduction:
And the key mapping for Oculus Rift in UE:
HTC Vive Key Mapping
For comparison with the above Oculus Rift, here is an HTC Vive key mapping:
HTC VIVE Device Setup
SteamVR 2.0 Base Station Positioning
The HTC Vive Pro supports SteamVR 2.0, which allows tracking to cover 150° and 7 meters, and supports daisy chaining of base stations (up to 16) for large space positioning solutions.
Note: The second-generation base stations do not support the first-generation HTC Vive headsets.
Using Proxifier to Route Oculus Traffic through SS Proxy
Yesterday, the company bought an Oculus Rift device, and during the installation, a global proxy was needed. On Windows, I used Proxifier to route the Oculus-related software through the proxy.
First, add a proxy in Proxifier:
Once the connection test is successful, you can proceed with the following operations.
After a successful connection, an additional proxy rule can be added. The relevant processes for the Oculus programs are as follows; what we need to do is route these processes through the SS proxy:
1 | OculusSetup.exe;OculusClient.exe;OVRServiceLauncher.exe;OVRServer_x64.exe;OculusVR.exe;OculusCompatCheck.exe;CompatToolCommandLine.exe;OculusLogGatherer.exe;OVRLibrarian.exe;oculus-driver.exe;OVRLibraryService.exe;oculus-overlays.exe;OVRRedistributableInstaller.exe; |
Fill the above content into the Application
text box and select the local proxy port for SS.
For other programs (like foreign games, Steam, etc.), if they need to be forced through the SS proxy, the same method applies.
VR Screen Blur Issue
Since the default Screen Percentage value in UE projects is quite low, the visuals may appear blurry. However, increasing it directly can lead to significant frame rate drops.
Typically, a setting under 200 will provide good visual quality, and below is a list of recommended values (ideal values) for UE. Art designers should optimize the scene based on these to ensure frames are close to maximum.
Before UE 4.19 (excluding 4.19), the ideal suggested values for VR HMD (r.ScreenPercentage) are:
DeviceType | r.ScreenPercentage |
---|---|
Oculus Rift | 133 |
HTC Vive | 140 |
PSVR | 140 |
GearVR | 120 |
GoogleVR | 120 |
After UE 4.19, vr.PixelDensity
was added. When r.ScreenPercentage
is set to 100, standardized values can be used across different platform devices:
DeviceType | r.ScreenPercentage | vr.PixelDensity |
---|---|---|
Oculus Rift | 100 | 1 |
HTC Vive | 100 | 1 |
PSVR | 100 | 1 |
GearVR | 100 | 1 |
GoogleVR | 100 | 1 |
Lower values will perform faster but will be undersampled (more blurry), while values over 1 will perform slower and will supersample (extra sharp).
This way, you can control the display quality through the standardized value of vr.PixelDensity
.
For further details, see the link: Significant Changes Coming To VR Resolution Settings in 4.19.
Solution for HTC VIVE Base Station Fault (03)
If the indicator on the base station flashes red and SteamVR displays Base Station Fault (03), try manually flashing the base station firmware. The steps are as follows:
The firmware path is under the Steam installation path: Steam\steamapps\common\SteamVR\tools\lighthouse\firmware\lighthouse_tx\archive\htc_2.0
, find the following two files:
1 | * lighthouse_tx_htc_2_0-calibration-rescue-244.bin |
- Ensure the base station is powered off, then connect it to the computer using a micro-B USB cable.
- Press and hold the mode button on the back of the base station and plug in the power cable.
- Release the mode button once the computer confirms a USB mass storage device.
- The connected base station’s storage device is named “CRP_DISABLED”; open it and delete the file “firmware.bin.”
- Copy the file “lighthouse_tx_htc_2_0-calibration-rescue-244.bin” to the storage space of the base station.
- After copying, unplug the power cable.
- Wait a few seconds, then plug the power back in. Do not press the mode button during this process. The base station should now rapidly blink green or red after a few seconds. A green light indicates successful recovery.
- If it blinks red, this indicates it cannot auto-repair; you need to send it for repair.
- Unplug the power again.
- Repeat steps 1 to 7, but in step 5, copy the file “lighthouse_tx_htc_2_0-244-2016-03-12.bin.”
- Once complete, the base station should return to normal operation. Set its channel to “A” and track it independently (keep the other base station powered off) to verify functionality. Once confirmed working, power on the other base station.
If the green light is blinking but cannot function properly, repeat steps 1 to 7, but in step 5 clear all files in “CRP_DISABLED” and only copy “lighthouse_tx_htc_2_0-244-2016-03-12.bin.”
- If manually flashing the base station firmware and recalibration does not work, use a phone to take a picture to ensure the two laser points are functioning normally (do not use iPhone/iPad as they cannot capture the laser points); if either of these laser points does not display, it indicates laser damage and should be sent to customer service for inspection.
Reference link: Base Station Fault (03)
Engine Analysis
Starting a UE Game
The game’s initialization starts from UGameInstance::StartGameInstance
. It is called by FEngineLoop::Init()
through polymorphic calls to GEngine->Start()
, which invokes UGameEngine::Start()
that calls GameInstance->StartGameInstance();
:
Actor Initialization in UE
AActor’s PreInitializeComponents
/InitializeComponents
/PostInitializeComponents
and DispatchBeginPlay
are all invoked in ULevel::RouteActorInitialize.
1 | void ULevel::RouteActorInitialize() |
UE4: Engine Start Order
UE Engine Tick Call Stack
1 | FEngineLoop_Tick=>start: void FEngineLoop::Tick() |
Game Flow on UE4
Actor LifeCycle
Actor Lifecycle on Unreal Engine
UE Log Macro Defined
Some Log definitions in the UE source code:
The logs defined in EngineLogs.h:
1 | ENGINE_API DECLARE_LOG_CATEGORY_EXTERN(LogPath, Warning, All); |
Defined in CoreGlobals.h:
1 | CORE_API DECLARE_LOG_CATEGORY_EXTERN(LogHAL, Log, All); |
Here are some recently used log definitions:
1 | // Module: Json |
Method to Detect if it is an Installed Engine Version
The engine version installed via EpicGameLauncher cannot create a Target Program
project using UnrealBuildTool.exe -ProjectFiles "ProgramProjectName"
, and will prompt the following error:
1 | ERROR: UnrealBuildTool Exception: A game project path was not specified, which is required when generating project files using an installed build or passing -game on the command line |
This exception in the related code in UBT is located in ProjectFileGenerator.cs
:
1 | // ProjectFileGenerator.cs |
As seen, if the -game
parameter is passed to UBT and it is an installed engine version (EpicGameLauncher), it will check if the project
parameter has been passed. If not, it will throw an exception.
A normal UBT call command:
1 | UnrealBuildTool.exe -ProjectFiles -project="D:\UnrealProjects\UEProject.uproject" -game |
This ordinary Game parameter won’t throw an exception in UBT. However, calling UBT with the command to generate the Program will throw an exception for the installed engine version:
1 | UnrealBuildTool.exe -ProjectFiles ProgramName |
According to the detection code in ProjectFileGenerator.cs
above, what we need to do is make the result from UnrealBuildTool.IsEngineInstalled()
return false.
Continuing with the code: UnrealBuildTool.IsEngineInstalled()
gets a boolean variable bIsEngineInstalled
in UnrealBuildTool
:
1 | // UnrealBuildTool.cs |
Searching for references reveals that there is a place where bIsEngineInstalled
is set in GuardedMain
:
1 | // UnrealBuildTool.cs |
From the code, it’s clear that UBT detects whether it is an installed engine version using three methods:
- Check if the parameters include
-installled
and-installedengine
- Check if the parameters include
-notinstallengine
- Check if the engine path
Engine\Build
has theInstalledBuild.txt
file
(Technically, it’s two methods; even if -notinstallengine
is specified, it still needs to check for the existence of Engine\Build\InstalledBuild.txt
).
The detection order is as follows:
1 | -installled > -installedengine > -notinstalledengine > Engine\Build\InstalledBuild.txt |
Thus, when I want UBT to consider my engine version as not installed, there are two approaches:
- Call UBT with the
-notinstalledengine
parameter and delete theInstalledBuild.txt
file in theEngine\Build
directory. - Call UBT without passing the
-installled
and-installedengine
parameters and delete theInstalledBuild.txt
file in theEngine\Build
directory.
Note: UBT also has the following two detections:
1 | // UnrealBuildTools.cs |
UE: Get All Registered Engines
You can use IDesktopPlatform::EnumerateEngineInstallations
to get all the engine versions installed via the launcher and those registered by the user using UnrealVersionSelector
.
1 | TMap<FString,FString> Installations; |
UnrealVersionSelector Registered Engine Path
When registering the engine using UnrealVersionSelector, the registered engine path will be written to the registry:
1 | HKEY_CURRENT_USER\SOFTWARE\Epic Games\Unreal Engine\Builds |
The registry entry lpValueName
will be a generated GUID:
1 | // DesktopPlatformWindows.cpp |
UE does not directly provide a separate way in IDesktopPlatform
to get the list of engines registered by users using UnrealVersionSelector.
However, it includes functionality in EnumerateEngineInstallations
to fetch per-user installations
engines from the registry:
1 | void FDesktopPlatformWindows::EnumerateEngineInstallations(TMap<FString, FString> &OutInstallations) |
EpicGameLauncher Registered Engine Registry Path
As mentioned before, if it is a non-source version engine, when registering using UnrealVersionSelector, it will write to the registry:
1 | HKEY_CURRENT_USER\SOFTWARE\Epic Games\Unreal Engine\Builds |
Whereas from the version installed by EpicGameLauncher, it will write to another registry path:
1 | HKEY_LOCAL_MACHINE\SOFTWARE\EpicGames\Unreal Engine |
Its value is (from the exported registry):
1 | Windows Registry Editor Version 5.00 |
UE provides a method to obtain engines installed from EpicGameLauncher (via the IDesktopPlatform
interface):
1 | TMap<FString,FString> Installations; |
UnrealVersionSelector Registry File Associations
1 | Windows Registry Editor Version 5.00 |
Note: If you want to define a startup method for your own files, you can use this method.
UE Registered Compilation Version Engine Installation Path
UE provides the UnrealVersionSelector
tool to select engine versions/generate sln, and it can also be used to register local engines (non-Launcher installed engines such as self-compiled source engines) into the project’s right-click Select Unreal Engine Version...
list.
After analyzing the UnrealVersionSelector
code, its registration process is as follows:
1 | WinMain_Func=>start: WinMain |
The operation to write to the registry is in the FDesktopPlatformWindows::RegisterEngineInstallation
function.
The process involves writing the registered engine directory into a string entry in HKEY_CURRENT_USER\Software\Epic Games\Unreal Engine\Builds
.
When right-clicking Switch Unreal Engine Version...
, it will modify the EngineAssociation
value in the .uproject
file:
The call flow is as follows:
1 | WinMain_Func=>start: WinMain |
The operation for writing project files is in FDesktopPlatformBase::SetEngineIdentifierForProject
:
1 | bool FDesktopPlatformBase::SetEngineIdentifierForProject(const FString &ProjectFileName, const FString &InIdentifier) |
Thus, if you choose a project using a compiled version engine, you can open the .uproject
file with a text editor and see that the value of the EngineAssociation
field corresponds to the engine version value in the registry.
Note: Command-Line Parameters of UnrealVersionSelector
The command-line parameters supported by UnrealVersionSelector and their uses can be found in UnrealVersionSelector.cpp#L224:
1 | int Main(const TArray<FString>& Arguments) |
Resolving .uproject Right-Click Generation Failure
First, check the path of UnrealVersionSelector.exe
used in the right-click menu by opening the registry:
1 | HKEY_CLASSES_ROOT\Unreal.ProjectFile |
Then find the shell\open\command
entry to see where UnrealVersionSelector.exe
is located (if you haven’t installed the source version of the engine, it defaults to the Binaries path of EpicGamesLauncher), for example:
1 | "C:\Program Files (x86)\Epic Games\Launcher\Engine\Binaries\Win64\UnrealVersionSelector.exe" /editor "%1" |
Next, open C:\Program Files (x86)\Epic Games\Launcher\Engine\Binaries\Win64
and set UnrealVersionSelector.exe
to run with administrator privileges (right-click - properties - compatibility - run this program as an administrator).
GamePlay
Issue with UE Macro Library
When using a macro library in UE Blueprints, simply saving the macro library after editing is not sufficient; you must compile the blueprint using the macro library for changes to take effect. In essence, the compilation in the blueprint will directly expand the macros; otherwise, it will revert to the previously unmodified version. This issue exists in UE4.18.3, but I haven’t tested other versions.
Saved Directory of Project Packaged in Shipping Mode
The Saved directory for UE projects packaged under Development or DebugGame modes is present in either the project directory
or the target packed directory
and includes directories such as Autosaves
, Backup
, Config
, Logs
, Crashs
, SaveGames
, and so on.
However, for games packaged in Shipping mode, the Saved directory is not located in the target packed directory
. Instead, it is found in C:/User/%username%/AppData/Local/ProjectName
, where ProjectName
is replaced by your project name.
For more information about UE packing, you can refer to UE’s documentation:
RVO Obstacle Avoidance in CharacterMovement
The CharacterMovementComponent
has automatic obstacle avoidance functionality, and you just need to enable UseRVOAvoidance
.
However, remember to disable RVO avoidance after the character’s death to avoid issues with monsters attempting to avoid obstacles in open spaces.
You can use SetAvoidanceEnable
to disable it.
VR Bow Model Standard
The bow required for VR should be a SkeleMesh, with the root bone located at the grabbing position (ideally at the grip center of the bow). Additionally, for easier calculations, the model’s orientation is required to be as shown below:
This orientation is for simplifying the rotation calculations when a VR player grabs the bow:
When drawing the bow, the hand holding the bow provides the Roll rotation, while Pitch and Yaw are provided by the rotation required for the hand holding the bow to look at the hand pulling the bow.
All bows should adhere to the same model rotation standards, which is easily implemented in art, but can be cumbersome for different programs to adjust.
Furthermore, the model origin of the arrow should be at the tail of the fletching:
Creating a well-experienced bow is quite complex, with attention to detail being key.
An Implementation of Clothing Change in UE
In UE’s USkinnedMeshComponent, there exists a function:
1 | class ENGINE_API USkinnedMeshComponent : public UMeshComponent |
The gist is to make the current SkinnedMeshComponent
move with the pose of the NewMasterBoneComponent
.
We can use a set of models that share the same skeleton to implement the clothing change functionality, such as head, chest, legs, feet, and hands, allowing a character to have these five separate USkinnedMeshComponent
model components to represent different parts.
Have a body with an animated USkinnedMeshComponent
as the torso, and set the MasterPose
of the five USkinnedMeshComponent
parts to it.
At this point, all parts will move with the body’s animations, and to change clothing, you can simply modify the models of each part.
Compiling Blueprints to C++ Code in UE
UE supports compiling from Blueprints to C++ code. In the Project Setting
- Packaging
- Blueprints
, select either Exclusive
(only selected Blueprint resources will be generated in C++) or Inclusive
(all Blueprint resources will be generated in C++).
After making a selection, package the project; upon successful packaging, you can find the .cpp
and .h
files prefixed with the Blueprint name in the Intermediate\Plugins\NativizedAssets\Windows\Game\Source\NativizedAssets
path under the public
/private
directories.
UE Blueprint Function Library Cannot Be Called in UObject Objects
Creating a Blueprint Function Library in the editor and creating a function will yield an error if it is called in a blueprint Object
, stating:
1 | Function Requires A World Context. |
Writing a test Blueprint Function Library generates C++ code:
The generated C++ code is as follows (removing excess parts, all the code can be viewed here):
1 | // TestFuncLib_pf1448227310.h |
Directly copying the above code into a C++ blueprint function library allows it to be called in UObject objects… this is quite strange.
Placing Components into Bone Sockets in UE
In Blueprints, you can directly set the parent socket
property in the Blueprint Editor to place a component into a bone socket. The same applies in C++, although it’s slightly more complicated. Let’s look at an example from ShooterGame:
1 | // ShooterGame\Private\Weapons\ShooterWeapon.cpp |
The same AttachToComponent
is used here, and a Blueprint node with the same name can also be used to attach to bone sockets.
Getting OpenLevel Options in Unreal
When loading a level in UE, you can pass a FString
of options:
In the loaded level, you can retrieve it via GetGameMode
:
The C++ code looks like this:
1 | AGameModeBase* OurGameMode=UGameplayStatics::GetGameMode(this); |
Note: After switching levels, objects created in the original level will be destroyed. To solve this, use the GameMode’s GetSeamlessTravelActorList
to preserve specified Actors during level transitions.
Converting 3D Positions in Game Scene to Screen Positions
Setting Mouse Cursor’s Relative Position within Viewport
First, install the LowEntry-ExtendedStandardLibrary plugin. You can use the ULowEntryExtendedStandardLibrary::SetMousePosition
function to set the mouse cursor’s relative position within the viewport. The viewport size can be obtained via UWidgetLayoutLibrary::GetViewportSize
.
Mouse Focus is Not in the Window After Starting the Game in UE
You can use SetInputModeGameAndUI
to set the mouse focus within the window, and set InMourseLockMode
to LockAlways
. Using this action when starting the game will ensure the mouse focus is within the game window from the start, avoiding the need to click once on the game window to interact with UI.
Determining if a Particle Effect is Looping
If an Emitter
from a UParticleSystem
has Emitter Loops
set to 0, it indicates a looping effect:
UE provides a method to determine if a particle effect is looping:
1 | bool UParticleSystem::IsLooping()const{ /*...*/ } |
If there is at least one looping Emitter in the effect, then the effect is considered looping. However, this method is not exposed to Blueprints, so a function library can be written to encapsulate it for use in Blueprints.
Caution with Exported Symbols When Using Classes Across Modules
When inheriting/accessing classes within the UE engine, be cautious about whether the class has exported symbols. Classes without exported symbols cannot be linked to their definitions. For instance, the FParticleSpriteEmitterInstance
class in the UE Engine
module does not have exported symbols.
Creating Async Nodes in Blueprints
In projects with some asynchronous operation needs, such as downloading files, a download command waits for completion before callback execution, minimizing excessive event binding and unbinding operations. Some async operations like PlayMontage
and DownloadImage
have multiple output nodes:
Can we create our own such async operation node? Absolutely.
You can check the implementation of the DownloadImage node in Engine\Source\Runtime\UMG\Public\Blueprint\AsyncTaskDownloadImage.h
(C++API).
Here’s how to write one:
- The key is to inherit
UBlueprintAsyncActionBase
, which is mandatory. - Then write a
static
function that returns a pointer to the class, marked withUFUNCTION
asBlueprintInternalUseOnly="true"
. - Declare and define several dispatcher members, which are the async nodes (the exec nodes on the right side of the Blueprint node).
Let’s look at the declaration of DownloadImage
:
1 | class UTexture2DDynamic; |
Comparing with the above DownloadImage node, we can see:
0. First, a dynamic multicast delegate FDownloadImageDelegate
is declared with one parameter.
- The
UAsyncTaskDownloadImage
class declares two event dispatchersOnSuccess
andOnFail
, akin to the Blueprint node’s right-side exec and parameterTexture
, fundamentally being dispatchers (dynamic multicast delegates). - The
static
functionDownloadImage
receives a FString parameter and returns aUAsyncTaskDownloadImage*
, which displays the dispatcher execution nodes in the Blueprint.
In essence, the declared dynamic multicast members and their parameters will show on the right side of the Blueprint node.
I implemented an async action operation: first, look at the Blueprint operation:
The operation involves creating an AsyncActionObject
object to trigger the async operation and then executing CreateAsyncTask
to bind events to the previously created AsyncActionObject
.
You can then call operations like OnActionStart
on the ActionObj to trigger the relevant nodes on the right side of CreateAsyncTask.
Note: I imposed a restriction that one object corresponds to one task. If the currently passed AsyncActionObject
is already bound to another task, creating the task will fail.
Now the code:
1 | // AsyncTask.h |
Next is the implementation:
1 | // AsyncTask.cpp |
Declaration for the AsyncActionObject class:
1 | // AsyncActionObject.h |
And its implementation:
1 | // AsyncActionObject.cpp |
Essentially, it wraps two layers of dispatchers…
For example, it allows you to listen in a behavior tree for an animation being terminated or completed before executing other actions, thereby solving coupling between different modules.
Warnings/Errors When Referencing Windows Header Files in UE
If you’ve used windows.h
in UE, you might encounter errors like 4668 in VS. Previously, this was only a warning, but in UE4.18 it became an error. UE has encapsulated the Windows API header files, allowing you to include the appropriate ones:
1 |
|
Alternatively, you could use:
1 |
Additionally, if you use Windows API functions such as windows.h
, you may encounter errors like this:
1 | 1>C:\Program Files\Epic Games\UE_4.15\Engine\Source\Runtime\Core\Public\Async/TaskGraphInterfaces.h(892): error C2039: '__faststorefence': is not a member of 'FWindowsPlatformMisc' |
To resolve this, avoid including these Windows API header files in UE header files; instead, move them to the corresponding .cpp files.
Getting the Cursor’s Relative Proportion in the Window in UE
First, obtain the current window size through UGameViewportClient
to get the SWindow
, which allows you to retrieve the window size with SWindow::GetSizeInScreen
:
1 | void GetWindowSize(bool& Success, int32& Width, int32& Height) |
Next, to get the cursor’s position in the current window, you can use APlayerController::GetMousePosition
(it also retrieves position via the viewport):
1 | bool APlayerController::GetMousePosition(float& LocationX, float& LocationY) const |
Then dividing the two results yields the relative position of the cursor within the current window.
Gamma Value of SceneCapture2D in UE
When using USceneCapture2D
to capture the scene to a RenderTarget
for display on the screen via Spectator Screen
, you may find the colors are incorrect:
To solve this:
- Set the SceneCapture2D’s
CaptureSource
toFinal Color (LDR) in RGB
- Set the RenderTarget resource’s gamma value to
2.2
to match the original image closely.
A Trick with Event Parameters in Blueprints
In some plugins, you might see operations like this:
In reality, parameters of event nodes in Unreal Blueprints are class member variables (data members of the class), allowing their usage in other places directly.
Other similar issues include delay operations:
Collision Detection Issues with UProjectileMovementComponent in UE
When using the UProjectileMovementComponent for functionalities like arrows, collision might not trigger due to excessive speed. It’s noted as a point for further research.
Config and Editor
Changing the Esc Key Shortcut to Exit the Editor Mode in UE
Open Editor Preferences
- Keyboard Shortcuts
to modify the key for Play World(PIE/SIE)
.
Displaying Plugin Content in UE Editor
Modifying the Parallel Build Count in UE
Edit the following files:
1 | Engine/Saved/UnrealBuildTool/BuildConfiguration.xml |
As shown:
1 |
|
MaxProcessorCount
specifies the maximum number of processors for local execution. More configuration parameters can be found in the UBT configuration.
Packaging Android Data in OBB Files in UE
Stuttering when the Editor Window is Out of Focus in UE
When running UE on the Windows platform, if you play a game within the editor while the current focus is outside of the editor/VR app, CPU usage decreases, leading to stuttering (this issue doesn’t occur in packaged builds). This is due to UE performing checks on focus in the editor environment:
1 | // Runtime/ApplicationCore/Private/Windows/WindowsPlatformApplicationMisc.cpp |
Simply comment out FPlatformProcess::Sleep(0.005f);
to resolve the issue.
Fixing Chinese Character Encoding Issues in UE Editor’s Compile Logs on Win10
Note: Some software might have encoding problems (like GBK encoding showing garbled text).
Package
ObservedKeyNames.Num()>0
For detailed solutions, look at: UE Package Error: ObservedKeyNames.Num()>0.
UE Package Error: RenderDocPlugin
RenderDocPlugin: Error: unable to initialize the plugin because no RenderDoc library has been located.
The solution: Disable the RenderDocPlugin before packaging.
UE4 Packaging 32-bit Alignment Error
When selecting the 32-bit platform for packaging in the engine, the following error may occur:
1 | error C2719: 'SpawnTransform': formal parameter with requested alignment of 16 won't be aligned |
This is due to using pass-by-value to transfer FTransform
in the code:
1 | AProps* SpawnProps(FTransform SpawnTransform); |
Because FTransform requires 16-byte alignment: Math/TransformVectorized.h#L36
1 | MS_ALIGN(16) struct FTransform |
The MS_ALIGN
macro is defined in Core/Public/Windows/WindowsPlatform.h#L131:
1 | // Alignment. |
So FTransform
requires 16-byte alignment.
FTransform is implemented using vector intrinsics, and instances of it need to have 16-byte alignment. I think the stack is guaranteed to be aligned to 16-bytes on Win64 so the compiler can pass it on the stack correctly, but there’s no such guarantee on Win32 (which is what we use for shipping builds).
Therefore, changing to pass a pointer or reference resolves the issue (both passing by reference and passing by pointer are sizeof(void*)
in size):
1 | AProps* SpawnProps(const FTransform& SpawnTransform); |
Related issues:
- Shipping: formal parameter with declspec(align(‘16’)) won’t be aligned
- FVector4 error not usable with x32 game package
UE Packaging Error Indicating File In Use
- Engine Version: 4.18.3
- Packaging Platform: Windows
- Running Mode: VR
- BuildConfiguration: Shipping
Error log during packaging:
1 | UATHelper: Packaging (Windows (64-bit)): Program.Main: ERROR: AutomationTool terminated with exception: System.IO.IOException: The process cannot access the file** ‘C:\YourProjectPath\Saved\StagedBuilds\WindowsNoEditor\Engine\Extras\Redist\en-us\UE4PrereqSetup_x64.exe’ **because it is being used by another process**. |
The UE packaging error message indicates is being used by another process because the EpicGameLauncher is also running in the process, so closing it before packaging resolves the issue.
Online
UE Actor Replication Config
Replication
OnlyRelevantToServer (default false)
If true, this actor is only relevant to its owner; if this flag is changed during play, all non-owner channels would need to be explicitly closed.
Always Relevant (default false)
Always relevant for the network (overrides bOnlyRelevantToOwner).
ReplicateMovement (default true)
If true, replicate movement/location related properties.
Actor must also be set to replicate.
- see SetReplicates()
- see https://doc.unrealengine.com/latest/INT/Gameplay/Networking/Replication/
NetLoadOnClient (default true)
This actor will be loaded on network clients during map load.
NetUseOwnerRelevancy (default false)
If actor has a valid Owner, call Owner’s IsNetRelevantFor and GetNetPriority.
Replicates (default true)
If true, this actor will replicate to remote machines.
see SetReplicates()
NetDormancy (default DORM_Awake)
Dormancy setting for actor to take itself off the replication list without being destroyed on clients.
1 | // This actor can go dormant, but is not currently dormant. Game code will tell it when it goes dormant. |
NeuCullDistanceSquared (default 225000000.0)
Square of the max distance from the client’s viewpoint that this actor is relevant and will be replicated.
NetUpdateFrequency (default 100.0)
How often (per second) this actor will be considered for replication, used to determine NetUpdateTime.
MinNetUpdateFrequency (default 2.0)
Used to determine what rate to throttle down to when replicated properties are changing infrequently.
NetPriority (default 3.0)
Priority for this actor when checking for replication in a low bandwidth or saturated situation; higher priority means it is more likely to replicate.
Replicated Movement
LocationQuantization Level: (default EVectorQuantization::RoundTwoDecimals)
1 | enum EVectorQuantization |
VelocityQuantization Level: (default ERotatorQuantization::RoundWholeNumber)
1 | enum ERotatorQuantization |
RotationQuantization Level (default ByteComponents)
Allow tuning the compression level for replicated rotation. You should only need to change this from the default if you see visual artifacts.
1 | enum ERotatorQuantization |
Disabling Auto-Connect in UE Editor for Multiplayer Testing
Issues Using UE for Online Networking
UE provides AController::IsLocalControlled
to determine whether the current controller is controlling a local entity:
1 | bool AController::IsLocalController() const |
Note: Be very cautious not to use the
AutoPossessPlayer
option in Pawn. This will cause the player’s Controller joining in to automatically act as Player0, leading to bizarre bugs.
Also available are UKismetSystemLibrary::IsServer
/ UKismetSystemLibrary::IsDedicatedServer
, which both get the current World
‘s GetNetMode
for judgment:
1 | bool UKismetSystemLibrary::IsServer(UObject* WorldContextObject) |
The members of enum ENetMode
and their meanings are as follows:
Name | Description |
---|---|
NM_Standalone | Standalone: a game without networking, with one or more local players. |
NM_DedicatedServer | Dedicated server: server with no local players. |
NM_ListenServer | Listen server: a server that also has a local player hosting the game, available to other players on the network. |
NM_Client | Network client: client connected to a remote server. |
NM_MAX |
Using UE OnlineSubsystem for Networking
UE’s networking can be implemented through CreateSession
/ FindSession
/ JoinSession
, but requires some simple configuration first.
Edit Config\DefaultEngine.ini
and add the following content:
1 | +NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="/Script/OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="/Script/OnlineSubsystemUtils.IpNetDriver") |
Note that unlike when interfacing with Steam, DefaultPlatformService
should be set to Null
; otherwise, you cannot join a Session.
UE Networking Client Not Navigating
In Project Settings
- NavigationSystem
, set Allow Client Side Navigation
to true
:
UE’s Session Not Discoverable in LAN
When creating a session with UE’s CreateSession
and trying to use FindSession
on another machine in the LAN, the session list cannot be found.
The cause of this problem is having VMs or VirtualBox installed on the computer; disabling the VMware Network Adapter
or VirtualBox Network Adapter
will resolve the issue.
The specific location in the Control Panel is Control Panel/ Network and Internet/ Network and Sharing Center/ Change Adapter Settings
:
Other Script
UE Strange Compilation and Linking Errors
After modifying the code, it’s best to delete the following files:
1 | Binaries |
The bat script is as follows:
1 | del *.VC.db |
Also search for Binaries and Intermediate in all plugin directories:
1 | $ find . -name "Binaries"|xargs rm -rf |
Profiling Commands
Show FPS
1 | stat FPS |
Show Statistics Units (total time per frame, logic thread/render thread and GPU time consumption):
1 | stat Unit |
Show Various Parameter Values in Render Thread
1 | Stat SceneRendering |
Show Render Thread Command Consumption
1 | stat RenderThreadCommands |
Show Parameters on Game Thread (AI/Physics/Animation/Blueprint/Memory Allocation, etc.)
1 | stat game |
Show Time and Efficiency Data Required for Culling
1 | Stat InitViews |
Show Lighting and Shading Render Time
1 | Stat LightRendering |
Capture Current Frame GPU Information
1 | ProfileGPU |
This will popup the GPU Data Visualizer
displaying the captured frame data.
Capture Profiling Information (CPU/GPU)
1 | stat StartFile |
This will generate *.ue4stats
files in the project’s Saved/Profiling/UnrealStats
folder, which can be opened using UnrealFrontend.
UE Network Analysis
1 | # Start and stop recording |
Captured data is saved under Saved/Profiling
with the extension *.nprof
.
Documentation for UE’s Network Profiler tool can be found at Network Profiler.
Links: