On little (Unreal) things and file sizes
(Boromir speaking) It is a strange fate that we should suffer so much fear and doubt over so small a thing. Such a little thing.
TL;DR
- Deep-dive look into the file size of an Unreal Engine tiny game;
- Checked for size differences when comparing the same game using Unreal versions 4 vs. 5;
- Attempted a few size reduction techniques between both engine versions (e.g. deleting unused plugins, unused materials and also using proper “Shipping” build config);
- Managed to reduce total file size by ~60% in each Engine version of the game.
- The upgrade from Unreal 4 to 5 brought an increase of 15% - 20% of the game’s final size;
- The overall experiment could prove inadequate in size/representativeness, drew some considerations about this in the end.
Side-note: Want to know more about creating a CI pipeline for your Unreal Engine project? Read my previous post!
Context/Lore (Press Y to skip)
Videogames are getting way too big… Literally! – A concerned gamer
The previous sentence has a horrifying amount of subtext:
- Are we talking from the perspective of Engines, Gameplay, Level Design, AI, Graphics, Sound, …
- Or how the chase for realism and fidelity in games impacts development time?
- Or is it a meta-critique on games being superficial/shallow/bloated nowadays?
- …
It’s a troll bait in gaming communities. And it’s not the purpose of this post. I want to look at a tiny slice of that sentence: Games being big as in their file and download size.
Again, this could open a whole Pandora’s box of discussion points, due to the subtext:
- Great games with small file and download size are a novelty and exception to the rule nowadays;
- On the one hand, it’s a delightful surprise that games like Valheim are 1.4 GB or the latest Zelda is around 16 GB;
- On the other hand: the (unpleasant) norm is that a non-indie game will take up anywhere between 100 to 250 GB;
- …
But… it’s not the purpose of this post.
I want to take it at a “Sub-atomic/Molecular level”. I’ll get to the point:
All this late talk about game file size made me curious:
- What’s the size of the smallest thing I’ve made so far in Unreal Engine?
- Could I optimize it and make it smaller?
So I went ahead, grabbed a 3 year old stale project I did when studying Unreal Engine 4, surely it was just a few MB (megaBytes) in file size, right? Hold up…
The Problem
Suddenly there was a problem where previously there was none. How does a bland super tiny game take up 600MB in file size?
For millennial context, that’s almost the entire size of a CD, and it’s half the file size of Valheim with 0.000001% of that game’s value.
The game itself, if we can call it a full game:
- Has (almost) no content;
- Has no menus or settings;
- Has no textures aside from dev-like textures;
- Has minimal physics and a few special effects;
- Has a single tiny level;
- Has dumb AI - 2 dwarfs that will spot the player if they are near…
- And the player can distract them by shooting decoys with a gun;
- Does not have in-game restart. When it’s
Game Over
orMission Complete
, we need to close the game withALT+F4
and reopen it again. - …
Here’s a video of what I’m talking about: https://youtu.be/_PE0yH3BuSE
At the end of the day, it was just an experiment for learning. Not a proper shippable game, but its size of 600 MB left me curious enough to go on a small expedition.
Side-note: random bit of context, just the development environment for both Unreal Engine 4 and 5 takes up about 150 GB of space… scream disappointed
Investigation/Solutions
Side-note: the repository used: https://github.com/filfreire/SimpleFPSTemplate_filfreire
After some research I took note of a few possible suspects:
- Unreal Engine will enable some plugins by default for every new project. These may add unnecessary bloat to projects. For example, there are plugins for integrating with Android which, if we’re not making mobile games, we probably can carelessly throw in the trash.
- When packaging the game, the default Build configuration is for
Development
builds. This will include all debug/developer tooling into the game, which adds to the size. - There could be materials and content that were included in the project that might not be used at all, and are just taking up space.
- Bonus: I was using version 4 of the Engine when I first did that project. How would size be impacted using Unreal Engine 5?
We’ll consider the baseline:
- Using Unreal Engine 4.27
- Default build without any optimization or custom package setting takes up 275 MB in a compressed
.zip
, roughly 595 MB when uncompressed.
Removing unused plugins
First we’re going to disable all plugins which we don’t use. Any plugins for different IDEs that we don’t use or other platforms like Android, iOS and others can potentially be removed. My project is also not a VR project, so pretty much all of that can be scrapped.
These were some of the plugins I initially disabled:
AndroidDeviceProfileSelector, AndroidMedia, AndroidMoviePlayer, OnlineSubsystemGooglePlay, AndroidPermission, GooglePAD, OpenXRHandTracking, MagicLeapMedia, MagicLeap, MagicLeapPassableWorld, LocationServicesBPLibrary, ExampleDeviceProfileSelector, IOSDeviceProfileSelector, LinuxDeviceProfileSelector, LuminPlatformFeatures, MLSDK, WmfMedia, WebMMoviePlayer, UdpMessaging, MobileLauncherProfileWizard, MacGraphicsSwitching, MobilePatchingUtils, AppleMoviePlayer, WindowsMoviePlayer, GoogleCloudMessaging, OnlineSubsystemNull, OnlineSubsystemUtils, OnlineSubsystemIOS, OnlineSubsystem, CLionSourceCodeAccess, CodeLiteSourceCodeAccess, KDevelopSourceCodeAccess, NullSourceCodeAccess, RiderSourceCodeAccess, XCodeSourceCodeAccess, PerforceSourceControl, PlasticSourceControl, SubversionSourceControl, OculusVR, OpenXR, OpenXREyeTracker, SteamVR
The final size after removing these plugins: compressed was 260MB, uncompressed 562MB.
That’s about 5% reduction in size. Not a massive change, but I suspect also not representative for most Unreal-based games. As comparison, take Hell Let Loose, a multiplayer tactical FPS. According to the game files, it currently uses Unreal Engine 4.25 and takes up about 38.9 GB. Reducing that game by 30 MB of plugins will still make it a 38.9 GB game, hence the reduction is a bit irrelevant/trivial 😅
Remove unused content
My next target was looking at potential unused content in the game. Some folks in the community (here’s one example, here’s another example) point out to this issue. Usually the recommendation is to look out for materials, say, textures, models and even entire levels that are unused in our final shipped game.
First, I looked into the size map of the content I had in the game:
The game specific content taking up about 67.5 MB meant that the bulk of the size was coming from another place. I deduced it would likely be Engine related. So I checked the size map of the Engine:
At first I thought this Engine specific content was impacting the final game size. I happily started deleting stuff. But upon closer inspection I was deleting stuff directly from my Unreal Engine install path. I had to repair my Unreal Engine installation afterwards and re-download what I had deleted 😅
It had no impact on file size.
There were a still few materials that caught my attention in the contents of my game. For example, I had a simple cube taking up about 11MB:
So I attempted to remove those. By removing materials like that the size of final uncompressed game was… *drumroll*… reduced by roughly 2 MB… 2MB?!
Epic fail.
Maybe I didn’t do it right. So I tried a different approach that some folks recommend of migrating assets into a new completely empty project.
If the project is just made up of Blueprints, then the migration is straightforward. In my case the project also had a handful of C++ source code, making the migration difficult.
This was a point also where the whole thing started to look like a rabbit hole. At the time of writing:
- I tried creating a “completely” blank project, and package it (with proper
Shipping
config which I will talk about in next section) and it occupied about 300 MB uncompressed… so a blank project was taking more space than my game project; - I wondered if it was perhaps an issue with the blank project I picked. I picked a different blank template, the First-Person-Shooter (FPS). Somehow that template took up about 340 MB uncompressed;
The sizes weren’t improving and it felt like a giant rabbit hole to get lost into. Since I wasn’t getting anywhere at the time, I skipped to the next reduction attempt.
Side-note: My untested hypothesis on the size difference of my project against blank projects is that the Engine version we start a project with affects the final size of the game later on. Even after we do successive conversions to more modern versions, the version we base our game initially will perhaps be missing stuff? I’m not sure. I was using Tom Looman’s SimpleFPSTemplate as a starting point, which was first released on Unreal Engine 4.17 and successively upgraded. Perhaps that had an influence in something, but it would require a handful of successive experimentation with different engine versions to get to the bottom of.
Setup Non-debug/Shipping build configs
One of the things that I overlooked when I wrapped this game prototype was the fact that the builds by default were still development builds. It was possible to open the developer console inside the game and see a lot of different debug information.
Unreal has a setting for Build configuration when Packaging that can be set to avoid including this development tooling in the final game.
I went ahead and attempted the suggested Shipping
configuration as opposed to the Development
one, and it helped a lot the file size reduction.
It nearly halved the size of my game prototype, going from 595 MB to bellow 250 MB when uncompressed. On top of that, removing both unused plugins and materials helped drop the size to 220 MB: a whooping 63% difference!
To set up this setting in an pre-existing CI pipeline is easy. Take an example batch script that packages the game:
set ueLocation=%~1
set projectLocation=%~2
set projectName=%~3
set target=%~4
set packageFolder=%~5
"%ueLocation%\Engine\Build\BatchFiles\RunUAT.bat" BuildCookRun -project="%projectLocation%\%projectName%" -nop4 -utf8output -nocompileeditor -skipbuildeditor -cook -project="%projectLocation%\%projectName%" -target=%target% -platform=Win64 -installed -stage -archive -package -build -pak -iostore -compressed -prereqs -archivedirectory="%projectLocation%\%packageFolder%" -clientconfig=Development -nocompile -nocompileuat
We only need to change the -clientconfig=Development
into -clientconfig=Shipping
plus add the -nodebuginfo
argument, and the Unreal Automation Tool does the rest.
Results for Unreal 4.27
Before going to Unreal Engine 5 comparisons, let’s do a catch-up. Here’s a table with all the results I had achieved up until this point:
Engine version | Action | Compressed (MB) | Uncompressed (MB) | Difference vs default compressed (%) | Difference vs default uncompressed(%) | Compression reduction |
---|---|---|---|---|---|---|
4.27 | base default | 275 | 595 | n/a | n/a | -53,8 |
4.27 | rm plugins | 260 | 562 | -5,5 | -5,5 | -53,7 |
4.27 | rm plugins + rm materials a bit | 260 | 560 | -5,5 | -5,9 | -53,6 |
4.27 | shipping version | 162 | 228 | -41,1 | -61,7 | -28,9 |
4.27 | shipping version + remove more plugins | 158 | 220 | -42,5 | -63,0 | -28,2 |
The key takeaways until now:
- Using the proper build configuration helps reduce a big portion of the size;
- Removing unused plugins materials might help improve the size of the final game… but the mileage will vary depending on the project.
And this is all for the exact same engine version (Unreal Engine 4.27).
How would we fare with the latest version?
Upgrading from Unreal 4 to 5
I was curious to see how the latest version of the Engine would impact sizes. I converted my 4.27 project for the 5.2 version of the Unreal Engine.
The compressed size was 308 MB, and uncompressed was 687 MB. Just by switching to a recent Engine version, there’s a 15% increase in uncompressed size.
I kept the upgrade to version 5.2 on a separate Git branch and attempted to run through the same steps I ran above for version 4.27, here’s a table with the results:
Engine version | Action | Compressed (MB) | Uncompressed (MB) | Difference vs default compressed (%) | Difference vs default uncompressed(%) | Compression reduction | Difference vs UE4 default(%) |
---|---|---|---|---|---|---|---|
5 | default | 308 | 687 | n/a | n/a | -55,2 | 15,5 |
5 | rm plugins + rm materials a bit | 297 | 669 | -3,6 | -2,6 | -55,6 | 19,5 |
5 | shipping version | 178 | 267 | -42,2 | -61,1 | -33,3 | 17,1 |
5 | shipping version + remove some more plugins | 171 | 238 | -44,5 | -65,4 | -28,2 | 4,4 |
In all reduction cases the 5.2 version always took up more space than the 4.27 version. The unused content removal didn’t impact the size in a meaningful way so I left it out of the table.
Similarly to Unreal Engine 4, in the case of my game there’s a difference of around 60% size reduction by removing plugins and setting up the “Shipping” build configuration when packaging the game as opposed to the development one.
There is an extra key takeaway. If we look towards the last experiment shipping version + remove some more plugins
, we’ll see that the final uncompressed size is not that much bigger than Unreal Engine 4. To understand the possible cause of this, we have to look at what was done in each:
- We applied the
Shipping
build config when packaging for both equally - We removed the same plugins and materials for both in a first stage
rm plugins + rm materials a bit
- But, the plugins we’ve removed at the final stage are different between engine versions.
On Unreal Engine 4.27 the final list of deactivated plugins was smaller than the one for Unreal Engine 5.2. This could probably be tuned further and revisited, but I was content with the results up to this point.
Side-note: the list of deactivated plugins for version 4.27 is found here and for version 5.2 it’s here.
Wrapping-up
There’s a few considerations to keep in mind:
As a baseline for reducing file size “any” Unreal Engine project, my the game prototype experiment is not an adequate sample. File size optimizations are not necessarily proportional to the game size.
I found comments on forums saying that Plugins that are enabled on the Unreal Editor but not mentioned in the .uproject
file shouldn’t impact size of the final packaged build of the game. What I’ve noticed is the opposite: for every attempt at disabling plugins I got some file size reduction out of the final game build.
My assumption on Unreal plugins, that they act as “plug in” extensions, but are not actually needed was incorrect: Disabling some plugins caused things to stop working. For example, disabling some AI related plugins would make my AI Dwarfs stop working and fail to detect the player.
There’s a lasting vibe I’m left with after this exploration. It was cumbersome to optimize the size of this tiny Unreal Engine game prototype. Just to give the reader an idea of frustrations I felt:
- There’s no way of knowing which Plugins are enabled but not actually being used by the game project. Disable plugins was a matter trial and a lot of error;
- The tooling does’t help developers catch unused materials. We can try to find things ourselves, again, through trial and error, but it’s a poor developer experience;
- I wonder how easy this is for experienced folks dealing with for complex projects. If it’s this hard for a simple game prototype, wouldn’t most game developers be tempted to skip this work entirely?
Lastly, all this beanie-babies “gold” rush of “AI” helping developers… I see plenty of examples of large language models assisting with bland/shallow content creation, even in the context of Unreal Engine games… but I can’t find anything intelligent out there in the lines of:
Hey we’ve noticed you are not using this 200 MB texture anywhere on your game, but it’s being included in the final build… would you like to unlink/remove it?”
This would be more useful for empowering game developers than just regurgitating text that was stolen parsed from crawling the web.
Side-note: This small investigation into the file size issue made me wonder… what would the size of the “same” game project be for the old Unreal Engine 3/UDK nowadays? I’d like to revisit this, even if it’s just for fun.
Future ideas
There’s a chance for a bigger creative exercise out the file size problem. Something like what folks do in the demoscene but applied to Unreal Engine 4/5 in terms of games with the smallest file size possible. That would entail a lot of creative solutions:
- The smallest thing that boots up - even if it’s not very “game-y” but is still built with Unreal;
- An actual proper game, with meaningful gameplay, art, sound, …, and that occupies the smallest size possible when compressed;
- And even throw the contest at existing games where game developers can apply with their existing game to see who managed to get the biggest reduction.
Something to consider for future posts. Next up, I want to look more in depth into the Unreal Test framework than I have in my past post.
There’s some bugs that could use some fixing and would be great to try some automated checks. I found a cool one while revising this game prototype, where I managed to both win and lose the game, and trigger both the Mission Complete
and Game Over
final messages at the same time 😅
Stay tuned for more!
Addendum
Update, July 31st 2023, Removing Prerequisites from packaged builds
A slight reduction is futher possible by disabling prerequisites installers when packaging the game.
By default Unreal adds to the final packaged builds some dependencies installers, like Visual Studio redistributables. For publishing a game out into the world these are for sure needed, but if it’s just a matter of sharing between developers that already have the same dependencies installed, it becomes a tiny size optimization in the builds used for testing.
By removing the -prereqs
argument when packaging the game with RunUAT.bat
, the following results were achieved:
- Unreal Engine 4.27 “Shipping” version of the game: 119 MB Compressed, 181 MB Uncompressed;
- Unreal Engine 5.2 “Shipping” version of the game: 122 MB Compressed, 190 MB Uncompressed;
If you read this far, thank you. Feel free to reach out to me with comments, ideas, grammar errors, and suggestions via any of my social media. Until next time, stay safe, take care! If you are up for it, you can also buy me a coffee ☕