Let cpu fans be quiet when UE4 Editor is in front

Two methods to solve this,

  • Modify source code,
    D:\ue\Engine\Source\Runtime\ApplicationCore\Private\Windows\WindowsPlatformApplicationMisc.cpp

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    #include <io.h>
    int doesFileExist(const char* filePath)
    {
    	int result = _access(filePath, 0);
    	if (result < 0)
    		return 0;
    	return 1;
    }
     
    bool FWindowsPlatformApplicationMisc::IsThisApplicationForeground()
    {
    	if (doesFileExist("d:/ue/not_focus.txt"))
    	{
    		return false;
    	}
     
    	uint32 ForegroundProcess;
    	::GetWindowThreadProcessId(GetForegroundWindow(), (::DWORD *)&ForegroundProcess);
    	return (ForegroundProcess == GetCurrentProcessId());
    }

    If d:\ue\not_focus.txt exists, whether UE4 Editor is active, UE4 will not occupy a cpu kernel thoroughly.

  • In D:\ue\Engine\Config\ConsoleVariables.ini, or in console, type

    1
    
    t.MaxFPS 5

refer to:
なんとなく日誌

UE4 blueprint memo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
Level Viewport
	bp_test
		Details
			Actor
				Tags
	Box Trigger
		Actor Hidden in Game
 
 
Level Blueprint
	1
		DestroyActor
	Event Tick
		Get All Actors with Tag
			Get Actor Location
			Set Actor Location
	Add Event for Trigger Box 1
		OnActorBeginOverlap
			cast to ThirdPersonCharacter
				begin_event
		OnActorEndOverlap
 
bp_test: Event Graph
	Event BeginPlay
		Exec
			Sequence
				Delay
					Print String
				Set Timer by Event
					Event
						test_event
					Return Value
						Promote to variable
							New Var 1
			If
				New Var 0
					true
						Print String
					false
						Print String
	Event Destroyed
	4
		New Var 1
			Clear and Invalidate Timer by Handle
	5
		Array Var 2
			For Each Loop
			Reverse for Each Loop
	6
		Struct Var 3 : Struct Type 3
			Break Struct Type 3
	7
		Enum Var 4 : Enum Type 4
			Switch on Enum Type 4
	Add Timeline
		Lerp Vector
			Set World Location
 
	test_event: Custom Event
		Exec
			Draw Debug Point
ThirdPersonCharacter : Event Graph
	begin_event: Custom Event
	Event Dispatchers
		hitDemon
	1
		hitDemon
Demon1 : Event Graph
	Get Player Character
		cast to ThirdPersonCharacter
			bind event to hitDemon
				add custom event
Demon1
	Details
		Collision
			Collision Presets
				Custom...
ThirdPersonCharacter : Blueprint
	Components
		ThirdPersonCharacter
			Use Controller Rotation Yaw
		CameraBoom
			Use Pawn Control Rotation
		CharacterMovement
			Orient Rotation to Movement
	1
		Capsule Component
			Get Word Location as Start
			Get Forward Vector
				x 10000
					+ Get World Location
						as End
							Line Trace By Channel
Get Player Controller
	Show Mouse Cursor
	ConvertMouseLocationToWorldSpace
 
Level Blueprint
	Q
		CubeMesh
			Static Mesh Component
				Create Dynamic Material Instance
					Set Vector Parameter Value
						Parameter Name : cube_color4
 
Mat_cube asigned to CubeMesh
	cube_color4 : Constant3Vector
		Base Color

In Actor Blueprint, enable input event,

1
2
3
4
bp_test: Event Graph
	Event BeginPlay
		Get Player Controller
			Enable Input

Questions,

  • Why can't 'Delay' function be used in 'While Loop'?
  • In Game mode, can't control previous character while incarnating into a new character?

    1
    2
    3
    4
    5
    
    ThirdPersonCharactor1
    	Details
    		Pawn
    			Auto Possess Player
    				Player 0

refer to:
我是一只好蛋YEAH
https://blog.csdn.net/sunday7279/article/details/88665577

Debug ue4 in Fedora35

After running Setup.sh and GenerateProjectFiles.sh, we found UE4.pro created. It's like a fresh breeze coming from the roof window, we are free now, no more need to fear the once unbearable torment in Visual Studio IDE.

Qt source is not necessary to ue4, qtcreator is only a visual debugger to ue4.

Build Steps:

1
make UE4Editor-Linux-Debug ShaderCompileWorker-Linux-Debug -j8

Clean Steps:

1
make UE4Editor-Linux-Debug ShaderCompileWorker-Linux-Debug ARGS=-clean -j8

refer to:
https://docs.unrealengine.com/4.27/en-US/SharingAndReleasing/Linux/BeginnerLinuxDeveloper/SettingUpQtCreator/

debug ue4 completely

The default "Debug Editor" mode will produce a beast of UE4Editor that we can't debug it thoroughly, for vs2022 needs over 10G memory to load relative pdbs and retrieve debug information, eventually our computer is over burden, and vs2022 corrupts, so we never so much as trigger a debug point.

After several mends, vs2022 IDE still corrupts at beginning of debugging, so we have to seek help from WinDbg or QtCreator.

There are two main causes why UE4Editor is so big:

  • The original build tool action is 'Modular' which generates many dlls and every dll contains a portion of the same low level library code. So we change the action to 'Monolithic':

    ue\Engine\Source\Programs\UnrealBuildTool\Configuration\TargetRules.cs

    ...
    		public TargetLinkType LinkType
    		{
    			get
    			{
    //				return (LinkTypePrivate != TargetLinkType.Default) ? LinkTypePrivate : ((Type == global::UnrealBuildTool.TargetType.Editor) ? TargetLinkType.Modular : TargetLinkType.Monolithic);
    				return (LinkTypePrivate != TargetLinkType.Default) ? LinkTypePrivate : ((Type == global::UnrealBuildTool.TargetType.Editor) ? TargetLinkType.Monolithic : TargetLinkType.Monolithic);
    			}
    			set
    			{
    				LinkTypePrivate = value;
    			}
    		}
    ...
    

    But I have tried building in monolithic mode, it's a suicide, literately, there are many duplicated symbols generated which fail the building. We have to return to modular mode.

  • Every call on logging macro carves '__FILE__' or '__FUNCTION__' in the binary which will also inflate the executable. So we change these macros to nonsense:

    ue\Engine\Source\Runtime\Core\Public\Misc\Build.h

    ...
    #define EUHAT_MINIMIZE 1
    
    #if UE_BUILD_DEBUG
    #if EUHAT_MINIMIZE
    	#ifndef DO_GUARD_SLOW
    		#define DO_GUARD_SLOW			0
    	#endif
    	#ifndef DO_CHECK
    		#define DO_CHECK			0
    	#endif
    	#ifndef DO_ENSURE
    		#define DO_ENSURE			0
    	#endif
    	#ifndef STATS
    		#define STATS				((WITH_UNREAL_DEVELOPER_TOOLS || !WITH_EDITORONLY_DATA || USE_STATS_WITHOUT_ENGINE || USE_MALLOC_PROFILER || FORCE_USE_STATS) && !ENABLE_STATNAMEDEVENTS)
    	#endif
    	#ifndef ALLOW_DEBUG_FILES
    		#define ALLOW_DEBUG_FILES		1
    	#endif
    	#ifndef ALLOW_CONSOLE
    		#define ALLOW_CONSOLE			0
    	#endif
    	#ifndef NO_LOGGING
    		#define NO_LOGGING			0
    	#endif
    #else
    	#ifndef DO_GUARD_SLOW
    ...
    

    We should notice NO_LOGGING is false, I attempted to set it true, but a lot of errors occured.

    At the end of ueDbg\Engine\Source\Runtime\Core\Public\Logging\LogMacros.h

    ...
    #if EUHAT_MINIMIZE
    	#undef UE_LOG
    	#undef UE_LOG_CLINKAGE
    	#undef UE_CLOG
    	#undef UE_SUPPRESS
    	#undef UE_SECURITY_LOG
    
    	#define UE_LOG(CategoryName, Verbosity, Format, ...) 
    	#define UE_LOG_CLINKAGE(CategoryName, Verbosity, Format, ...) 
    	#define UE_CLOG(Condition, CategoryName, Verbosity, Format, ...) 
    	#define UE_SUPPRESS(...) {}
    	#define UE_SECURITY_LOG(...)
    #endif
    

And if we wanna debug inline functions, modify this place:

ue\Engine\Saved\UnrealBuildTool\BuildConfiguration.xml

<?xml version="1.0" encoding="utf-8" ?>
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
	<BuildConfiguration>
		<bAllowXGE>true</bAllowXGE>
		<bUseInlining>0</bUseInlining>
	</BuildConfiguration>
</Configuration>

'bAllowXGE' means to turn on IncreBuild, while the prerequisite is we have very big memory.

There are still some nasty things to do:

  1. Invoking empty macro is considered as a warning 4390, existing unused variables is considered as warning 4101, they will cease ue4 compilation.

    ue\Engine\Source\Runtime\Core\Public\Windows\WindowsPlatformCompilerSetup.h

    #pragma warning (error: 4100      4102 4103                          4109           4112 4113 4114 4115 4116 4117      4119 4120 4121 4122 4123 4124 4125      4127      4129 4130 4131 4132 4133                4137 4138           4141 4142 4143 4144 4145 4146                4150      4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164      4166 4167 4168                4172      4174 4175 4176 4177 4178 4179 4180 4181 4182 4183      4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197      4199)
    
    #pragma warning (error:      4301 4302 4303           4306      4308 4309 4310           4313 4314 4315 4316      4318 4319      4321 4322 4323 4324 4325 4326 4327 4328 4329 4330           4333 4334 4335 4336 4337 4338      4340           4343 4344      4346      4348                4352 4353      4355 4356 4357 4358 4359           4362      4364      4366 4367 4368 4369                     4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384           4387      4389      4391 4392 4393 4394 4395 4396 4397 4398 4399)
    

    ue\Engine\Source\Programs\UnrealBuildTool\Platform\Windows\VCToolChain.cs

    ...
    			// Set warning level.
    			if (Target.WindowsPlatform.Compiler != WindowsCompiler.Intel)
    			{
    				// Restrictive during regular compilation.
    				// Euhat Modified
    				//Arguments.Add("/W4");
    				Arguments.Add("/wd4101");
    				Arguments.Add("/W0");
    			}
    ...
    			// Prevents the linker from displaying its logo for each invocation.
    			Arguments.Add("/NOLOGO");
    			// Euhat modified
    			Arguments.Add("/FORCE:MULTIPLE");
    ...
    

    'FORCE:MULTIPLE' means just to pick the first one of the same name symbols instead of complaining as a link error.

  2. ue\Engine\Plugins\Slate\SlateInsights\Source\SlateInsights\Private\SlateInsightsModule.cpp

    //IMPLEMENT_MODULE((UE::SlateInsights::FSlateInsightsModule), SlateInsights);
    
  3. ue\Engine\Source\Runtime\AudioMixer\Public\AudioMixerDevice.h

    		// make it public
    		FAudioPlatformDeviceInfo PlatformInfo;
    

    ue\Engine\Plugins\Media\BinkMedia\Source\BinkMediaPlayer\Private\BinkMediaPlayerPCH.h

    ...
    			//return mix->GetNumDeviceChannels();
    			return mix->PlatformInfo.NumChannels;
    ...
    //DECLARE_LOG_CATEGORY_EXTERN(LogBink, Log, All);
    ...
    

    ue\Engine\Plugins\Media\BinkMedia\Source\BinkMediaPlayer\Private\BinkMediaPlayerModule.cpp

    //DEFINE_LOG_CATEGORY(LogBink);
    
  4. ue\Engine\Plugins\Runtime\AR\Microsoft\HoloLensAR\Source\HoloLensTargetPlatform\HoloLensTargetPlatform.Build.cs

    bEnableUndefinedIdentifierWarnings = false;
    

The last thing kept in mind is don't build the whole resolution, for simultaneous compilations of projects can easily run out of memory. Just right click Engine/EU4 and build UE4Editor only.

ps: We use UnrealEngine-4.27.2-release.zip in this article.

UE4 Shader源码编译过程

在主程序里拼成一个文件WorkerInputOnly.in后启动ShaderCompileWorker.exe进程编译shader源码。以下是调试时记录下来的命令行

D:/ue/Engine/Binaries/Win64/ShaderCompileWorker.exe "C:/Users/euhat/AppData/Local/Temp/UnrealShaderWorkingDir/A1AF8D424B2A34C30CE4378EDE6A0EFB/2/" 14492 2 WorkerInputOnly.in WorkerOutputOnly.out -communicatethroughfile  -TimeToLive=20.000000 -Multiprocess

UE4的TMap实现原理

TMap的成员ElementSetType是TSet类型,此TSet的成员是

1
TTuple<Key, Value>

TSet类由两个动态数组组成,一个用于Hash表,一个是TSparseArray。

先说TSparseArray,其成员Data是TArray类型,即动态数组,TSparseArray的特点是通过空闲成员内部指针将空闲成员链起来,这样可方便增加删除操作,但其中的增加操作的Index是无法预先指定的。

所以TSet类又用到了一个动态数组用于Hash表,这样可以计算Hash Key找到指定Hash表项,这个表项存的是Hash桶的最后一个入桶的成员在TSparseArray数组中的Index,而其它相同Hash Key的桶成员都在最后入桶成员结构内部链起来了。