Unreal Engine - How to read unreal engine source code

Unreal Engine - How to read unreal engine source code

Created
Sep 28, 2023 02:10 PM
Tags

Introduction

The code base of Unreal Engine is so huge, that is not very friendly for beginners. This article is for those who do not know where to begin to implement either an editor tool or a gameplay feature. The content is all based on offcial Unreal Engine version 4.26.2 . If you have any problem or want to discuss with me, feel free to contact me through email!

When an Idea Arises

For instance, if I currently "require access to texture resources within terrain materials," my first action would be to investigate where in the engine these terrain materials utilize textures. The area that comes to mind is the "paint" section within the terrain material brush panel, which features a display for all the terrain material texture thumbnails.
notion image
We can use Widget Reflector to check UI code,
notion image
When opening the Widget Reflector, we can see the window as shown below.
notion image
When you click the 'Pick Hit-Testable Widgets' button, you can see the line number and the file name containing the code generating the selected widget, and the hierarchical structure. Press ESC to exit the selection mode.
notion image
The green bounding box indicates the location of the widget we are highlighting using the reflector. On the right-hand side, you can view the code location.
notion image
Use your favourite IDE to locate the code. We'll discover that the source of this Thumbnail is passed as a parameter.
notion image
First, let's examine the structure of 'Target.' We find that the structure of 'Target' is quite complex. At times like this, it's a good idea to check if there are any other clues. Let's search for ThumbnailMIC because we're looking for the assignment point. This way, we can pinpoint it swiftly.
notion image
To confirm that we've located the correct code, we should investigate how this function is used. In this case, we find that only two instances employ this function.
notion image
By selecting the one associated with the image, we observe that the thumbnails in the TargetList are assigned through a loop. The assignment code can also be found below. Another straightforward but effective method involves placing breakpoints at all the locations where the function is used and inspecting the call stack when the breakpoints are triggered to ensure the execution flow aligns with your expectations.
notion image
Now, let's step into GetLayerThumbnailMIC and discover that the editor uses layer names to match the LayerInfo in FStaticTerrainLayerWeightParameter. We've successfully achieved the initial goal. For instance, if we want to obtain the resource of 'Layer00,' we can utilize this method to locate the StaticMaterialParameter and employ functions like GetTextureParameterValue.
 

Use String Constants and Console Variables to help pinpoint the code

For some challenging-to-track-down code, such as instances when Widget Reflector occasionally leads to rather general code, we can use strings or console variables for pinpointing the desired location.

Example of using String Constants

notion image
Suppose we want to add a button in the toolbar of our customized EditMode. If we use widget reflector, it may lead to the place where shows how the button is created, not how to add it in the EditMode. Since most of the widgets in the editor have string constants as hover tooltips, we can pinpoint our results by deducting them from the filename.
notion image
Now we can find multiple results. And in this example, we want to investigate the ‘Noise’ tool in the ‘Paint’ tab. We can eliminate unwanted answers by looking at the context.
 

Example of using Console Variables

In this part, I may use my living example. I wanted to find out how to control streaming the texture resources. I know there is a console variable called r.Streaming.Poolsize, and it controls the pool size allocated by the engine for streaming resources. So I thought there could be one for texture streaming specifically, and I searched for texture streaming and this showed up which confirmed my guess.
notion image
(To open the console, press the "`" key (located to the left of the "1" key.)
This r.TextureStreaming is, in essence, similar to using strings. To locate it, you can search for r.TextureStreaming and find the 'CVarTextureStreaming' variable.
notion image
To locate it, you can search for r.TextureStreaming and find the CVarTextureStreaming variable. “CVar” stands for console variables, and according to Unreal's naming conventions, you can use the name of such variables for searching.
notion image
After searching, you'll notice that only three files are using this variable. By examining the names of these files, you can pinpoint the location of the Texture Streaming settings.
 

Semantic Searching

If the methods mentioned above don't yield results, you can employ semantic searching, which requires some techniques.
For instance, when you want to find materials related to the GPU-driven mesh drawing pipeline, diving blindly into the codebase might prove challenging due to its generality. However, you can be certain that this functionality involves the use of compute shaders. Therefore, start by searching for shader files, such as .ush or .usf, with "GPU" as the prefix.
notion image
Next, examine the search results below. Only five files match our criteria, so you can select any of them for further investigation. Let's choose GPUSkinCache.ush in this case, as GPU skinning utilizes compute shaders to calculate skin mesh movement every frame.
notion image
With "GPUSkin" as your new keyword, you can locate GpuSkinCacheComputerShader.usf, which likely contains the code you're interested in.
notion image
Now, try searching for numthreads, as it defines thread allocation for the compute kernel immediately after it. You'll find that SkinCacheUpdateBatchCS serves as the entry point for the compute shader.
notion image
You can now use this function name to reverse-search the file containing its definition.
notion image
Here's another real-world example: I wanted to learn how to generate transient render targets. Without prior knowledge, I simply searched for "TransientRenderTarget" (case-insensitive). As shown in the image below, I found the information I needed. Remember, if you can't find answers online, they may be hidden within the official engine source code.
 

Utilize All Available Resources and Keep Experimenting

If none of the approaches mentioned above suit your case, consider seeking assistance on community forums or the official Discord channel. However, I recommend asking for help only after you've exhaustively tried every possible solution. In most cases, the three methods described above should suffice for tool development. However, they do require some familiarity with the Unreal Engine. So, don't hesitate to write code as a beginner. With practice, you'll gradually discern the coding patterns used by experts, empowering you to create whatever you envision.
Â