How to Build A Tiny UE4 Application

Tools and techniques for profiling disk occupancy

Sam Birley
XRLO — eXtended Reality Lowdown
6 min readSep 23, 2020

--

Magnopus UK

As developers, we have a responsibility to the user to not waste their time, bandwidth, and available local space. Moreover, for mobile apps, there is a strong observed correlation between the size of the app reported on the app storefront and the install conversion rate.

Maintaining as small an app as feasibly possible is therefore clearly an important part of the development process, up-there-but-not-quite-as-important as runtime performance. However, whilst we have a wealth of performance profiling tools exposed to us these days in any modern engine, the set of tools available for profiling generated build sizes is woefully limited.

In this post, we will explore a simple means of profiling precisely how a build app’s on-disk footprint breaks down, which will enable you to understand where all those bytes are going. We will be focusing on profiling the disk occupancy of UE4 content in a build, rather than the binaries. However, for more info on how you can make efforts to bring the general size of a build down, we strongly recommend checking out Epic’s documentation on reducing APK size, most of which is, in fact, applicable to any platform.

Unpacking A Build

So, you have a build and you want to understand what content is included therein, and more importantly, what’s taking up so much space. The first thing to know is that Unreal writes all asset data (blueprints, textures, meshes, etc) to ‘pak’ files, and by default, it writes all content data to a single pak file.

Finding the UE4 Pak File in a Cooked Build

On Windows, this file can be found by simply navigating to Content/Paks/MyProjectName-WindowsNoEditor.pak.

On Android platforms, there are a couple of extra hoops to jump through:

  1. Unzip your build .apk with your preferred zipping tool (apks are just normal zip files with some files whose presence is required in the zip).
  2. Within your zip, navigate to the assets directory to find the Android obb file which will always be named ‘main.obb.png’ (why png is anyone’s guess).
  3. This again is just a regular zip file masquerading as something else and needs unzipping; the simplest means to do so is to rename the file’s extension from ‘.png’ to ‘.zip’ and then unzip.
  4. Within the unzipped obb.png directory, the directory structure should start to resemble what we saw on Windows; navigate to MyProjectName/Content/Paks and you’ll find our friend MyProjectName-Android_ASTC.pak.

Unpacking The Pak File

As mentioned, UE4’s pak file format is unique to UE4, so no standard decompression tools can help us here. Thankfully, ‘UnrealPak’, the same command-line tool that Epic uses as part of their build process to generate the pak files, is also capable of decompressing pak files again.

Assuming you are using UE4.25 on Windows, and want to dump the unpacked contents to C:\MyUnpackedContent, your command will look something like:

There’s an important gotcha here that often trips people up. The UnrealPakTool requires paths to be fully qualified. Without fully qualified paths, the tool will gracefully fail to extract, reporting no obvious errors — we’ve seen this frequently cause confusion. Argument ordering is also not well documented, but a safe rule of thumb to follow is:

C:\Path\To\UE4\Binaries\UnrealPak.exe C:\Fully\Qualified\Path\To\Pak.pak -extract C:\Fully\Qualified\Path\To\Desired\Unpacked\Files\Root

Assuming all that goes to plan, you should just have to wait for a minute to allow the tool to extract all files to the specified directory before it then exits gracefully.

Profiling Occupancy Of The Content

So, having run the unpack process, our content that has been built for our target platform is sitting under our specified unpack directory in a loose manner, organised by the same subdirectory structure we used within the project to organise it at edit-time (which is handy for navigability). We now have everything we need to profile the disk usage of our content.

Humans are notoriously visual creatures, and often the best means of understanding the behaviour of a tool is by visual means (graphs, animations, heatmaps, etc). So to profile our build, we prefer to use a tool that facilitates this. In this article, we are using WinDirStat.

Firing up the disk utilization tool of your choice, point it specifically at the root unpack directory we gave UnrealPak, and then let it do its thing.

Once it has run, you’ll be presented with a visualisation that allows you to understand what the heaviest files in your project are, at a glance.

In the example above, we can see that the massive blue chunk (corresponding to the Map_Terrain mesh) occupies more space than any other coloured square, indicating it is the biggest single file among all our content, and so a likely contender for optimisation. Clicking on the square gives us the relative path to the content, along with the name of the content. More than enough to start filling in Jira tasks for the art team!

Automation

This process is already pretty awesome and can be a great tool to keep a lid on app sizes throughout development. However, around the tenth time you run it, you will start to wish for automation. None of the steps change between profiling sessions, and indeed the only variables in the whole process are project name, version of UE4, and platform, so it is a great candidate for automation.

At Magnopus UK, this is exactly what we have done. The steps outlined in this article up to the visualisation of occupancy step are executed in a python script as a build step on one of our continuous integration agents, executed after UE4 has finished generating the build. To visualise the script, however, we wanted a means of embedding the visualisation on the web page associated with the build on CI.

The approach we landed on first generates a json file describing the directory structure, files, and file sizes of all items in the root unpack directory and then embeds that json file in a template HTML file. With the json data injected, the HTML file displays a navigable view of the data using an awesome d3 sunburst visualisation. By default, we show the visualisation at the root directory level, with a finite amount of subdirectories down from there, but clicking on any element makes that the new root and subdirectories/files of that root are then displayed, allowing for fast and easy traversal.

This has enabled us to not only forget about the manual labour previously required to understand UE4 app sizes, but also to expose this to all members of the team at a glance, and to have that data for every single build — particularly useful when trying to diagnose what changes suddenly caused the build size to spike.

We are huge fans of CI/automation at Magnopus UK, and automating the profiling of UE4 app disk occupancy has gone a long way to solving our original goal of promoting the maintenance of app size as a value within the team. Look out for more fun with CI posts in the future!

--

--