What gets packaged into my iOS game and how do I control it?

What gets packaged into a cooked mobile game and how do I reduce the .ipa download size?

Cheers,
Michael Noland

There are a number of things that affect the size of a packaged iOS game, from the content it references to the build configuration you choose.

Target Configuration

One of the biggest changes comes from targeting the Shipping configuration instead of Development, which saves 31 MB. The Shipping configuration uses higher optimization settings, and removes debugging symbols and much of the logging and profiling code, resulting in much smaller executable sizes.

Example numbers from Tappy Chicken

Here are some example numbers from cooking and packaging TappyChicken for iOS in the 4.0.1 branch (Note #1).

The overall Shipping IPA is 43.8 MB uncompressed (34.8 MB compressed), which breaks down into:

  • 3.9 MB - Loading screens and icons (about the same compressed)
  • 25.5 MB - Executable (never compressed; Note #2)
  • 10.6 MB - Engine content (4.8 MB compressed)
  • 3.7 MB - Game content (0.7 MB compressed)

The executable is never compressed and the icons/screens are already compressed, but the game and engine content compresses quite well. (Note #3)

We will continue to work on reducing the amount and size of required engine content over time, as well as look at optimizing the executable size.

The Loading Screens and Icons are .png files that you create; you can provide fewer variations (Tappy Chicken has one for all the devices) or use more solid fills/etc… to reduce their size further.

Game content references

The size of game content is entirely in your hands; it ends up very reasonable for a small game like Tappy Chicken but it can easily blow out when you add a bunch of extra content.

It’s important to understand that any content referenced in your game will get cooked; some common gotchas are referring to huge otherwise unused textures as the default for a texture sample in a material function or material, or referencing unused content in an disconnected node or unused variable in your blueprint. These count as referenced even if all of your material instances replace them with something else. You can look in the cooked asset folder and if you spot any unexpected assets, use the Reference Viewer to track down who refers to it.

C++ versus content-only projects

Content only projects have a larger executable since they cannot make any assumptions about which plugins and libraries you are using. You can usually shrink your executable a little bit by switching to C++, and disabling unnecessary plugins and libraries at compile time (via EnabledPlugins and the Project.Build.cs and Project.Target.cs files). However, we have an optimization to remove more than 30 MB of Slate assets in content only games since they cannot use Slate. If you make a C++ project that doesn’t use Slate, you can save this space by setting bUsesSlate = false in the constructor of your TargetRules class in Project.Target.cs.

Notes

  1. I’m using PC->iOS for this test, and will post Mac->iOS numbers shortly, as there are currently some differences in the code paths that could result in different sizes (related to compression and symbol stripping).
  2. We never compress the executable since it is encrypted when uploaded to the App Store and won’t compress at all there.
  3. Cooking via Launch or the Game Launcher won’t currently compress the IPA on the PC → iOS deployment path. I added IPPArguments += " -compress=best"; to IOSPlatform.Automation.cs to get the compressed numbers mentioned above.

Cheers,
Michael Noland

Some additions to Michael’s answer.

We determined today that the shipping executables built on a Mac for iOS are not properly stripping their symbols, so they are about 20-30MB larger than they should be. I have fixed this and it should be in a future release. This makes the Tappy Chicken example IPA around 33MB in total size (with compression).

If you want to fix this on your own for now, you will need to run the strip command from a terminal window on the executable in question. To strip the executable for content-only projects, execute the following commands in in a terminal window:

cd /Applications/Unreal\ Engine.app/Contents/UE4/InstalledApps/4.0/Engine/Binaries/IOS

strip UE4Game-IOS-Shipping