Reducing the size of your iOS or Android game (Unreal Engine 4)

Looking to reduce the size of your UE4 iOS or Android app? Here is a handy list of the things I've done to reduce the size of Garden Wars and get under those pesky size limits (this is applicable to UE 4.13).

Measuring the app size

First of all, the way I check out the size is using 3 free programs: 7-zip, UnrealPak and WinDirStat (optional).

  • 7-zip will happily open .ipa & .apk packages, and in there you can see the packed sizes of things.
  • UnrealPak can be used to extract your pak file content and see what got packaged. Make a .bat file with this line in it:

    %~dp0\..\..\UE4\4.11\Engine\Binaries\Win64\UnrealPak.exe %1 -extract %~dp1\extracted

    ...then just make a shortcut to the bat file on your desktop - after that you can drag any pak file onto it, then find the extracted contents right next to your pak file.

  • WinDirStat is a handy filesize visualiser that gives you a colourful view of a folders contents, so you can very quickly see what the biggest users are. Once you have extracted your pak file, you can tell WinDirStat to analyze the extracted pak contents - you will most likely see huge music files, huge font files and some large engine materials.

Reducing the app size

Now here is what I do to reduce size:

  1. In my experience the single biggest win you can get is having a good PakBlacklist.txt in your Project\Build\IOS folder (or Android). Here is mine if it helps. You could probably add a lot more to it if you wanted to be more meticulous and daring. Note that you can save a large amount by removing certain engine fonts as well (LastResort, NanumGothic, DroidSansFallback), but you need them if you want to display Asian/Russian languages.
  2. Make sure in your packaging settings, you are packaging for shipping/distribution, you are using package compression, and you are using a pak file.
  3. Make sure you are compressing your PNGs (splash screens, icons) appropriately.
  4. Music files are huge in the big scheme of things - try to compress the imported sound wavs as heavily as you can (you can make that number pretty small before you notice a difference on a phone speaker), or even reduce the number of music tracks you are using.
  5. Make sure you're not including the armv7s binary on iOS, not really necessary (and I think it defaults to off now anyway).
  6. There are also some specific shader permutations you can disable at the bottom of the rendering section in project settings, to maybe save a little (assuming you're not using them), and probably other settings you could experiment with too.
  7. Go through all plugins and disable all the ones you don't need. e.g. for iOS you don't need the Android media player and vice versa
  8. Remember to do a fixupredirects on your content before shipping, leftover references can add up.
  9. I also deleted all unused maps and assets manually - for some reason, certain materials were getting cooked & packaged even though they were never used/referenced by anything.
  10. I opened up WorldGridMaterial and DefaultMaterial, and replaced their shader inputs with constants to reduce the size of those large materials (I also tried changing them to unlit but it seemed to cause crashes).
  11. Lastly, if you're compiling (i.e. you have the github version of the engine), you can change some build flags to reduce the code size - in your Project\Config\IOS\IOSEngine.ini:
  • WARNING: if you have bCompileICU=false, it appears to break localisation, if you use it
  • I get compile errors if I try to have bCompileRecast=false, so I leave that in
  • I use the UMG widget, so I leave bCompileCEF3 as true
  • I seem to remember either bCompileLeanAndMeanUE=true or bCompileForSize=true actually causing my IPA to be bigger... not sure why. It'd be great it someone from Epic or just someone who knows their way around the engine code could elaborate in more detail as to what those two actually do, and if they have any drawbacks... bCompileForSize sounds like its prioritising size over performance, or something... kinda like bRuntimePhysicsCooking=True

I end up with a "Universal" IPA of ~123MB. Once they're processed by the App Store, the individual sizes for all devices range between 82-89MB, thanks to iOS 9 app thinning, I think (the universal is only large because it has binaries for all phones in it). I'm guessing the universal IPA size doesn't really matter and that most people can download it over the cellular network since the downloads for each device are well under 100MB.

The final ~123MB universal IPA consists of: 82.5MB engine code (this is what gets reduced once you upload) + 12MB engine content + 10MB of my game content + 16.5MB of audio + 2.5MB startup movie / icons / splash screen.

On Android, the APK only comes to about 47MB (without any compiler flag changes).

Overall I'm happy enough with the size I got to. I feel like there is a whole heap of code I could rip out of the engine for this tiny game (if I had lots of time... and knew how to program), and a few more things I could do with my content to reduce size, but it starts to get a bit dodgy and not worth the trouble :)