IntroductionWhen an Idea ArisesUse String Constants and Console Variables to help pinpoint the codeExample of using String ConstantsExample of using Console VariablesSemantic SearchingUtilize All Available Resources and Keep Experimenting
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.
We can use Widget Reflector to check UI code,
When opening the Widget Reflector, we can see the window as shown below.
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.
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.
Use your favourite IDE to locate the code. We'll discover that the source of this Thumbnail is passed as a parameter.
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.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.
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.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
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.
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. (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.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.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.
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.
With "GPUSkin" as your new keyword, you can locate GpuSkinCacheComputerShader.usf, which likely contains the code you're interested in.
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.You can now use this function name to reverse-search the file containing its definition.
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.
Â