Developing an iOS game in Unreal is possible but can be tricky. In this article, I want to give you solutions to the problems I encountered during my work with iOS. Some of them may seem obvious but you can grab them and save your time and frustration.
I assume we all have a basic knowledge of building iOS games so I will skip the step-by-step tutorial and focus on issues.
All the steps below are the same for UE4 and UE5 projects.
Issue #1: Permission denied
As you all know when we want to create a game for iOS we need an Apple certificate and provision profile. If we cannot access the certificates page or we cannot see the plus sign (+) to create a new certificate on your Apple Developer account, we probably don’t have permission for doing that. We need to contact our IT guy for help. Otherwise, we can’t do much.
For me, this was the biggest issue when I started porting my first game to iOS.
Issue #2: Private key for certificate
After creating the certificate in the Developer portal, we need to generate a private key for it on Mac. Please make sure you do this on Mac’s administrator account. It may save you some trouble later.
Please unlock the System Keychain and import the .cer file. The system should generate a private key for your certificate automatically. It will be connected to your certificate in the KeyChain.
Now we just need to export it as a .p12 file and import it to the Unreal project on Windows.
Issue #3: Crash at Editor’s startup
When I opened Editor on the fresh project. I was welcomed by this error:
It was caused by the Preview Rendering Level set to Android by the previous developer. I didn’t set up my environment for Android development so when the Editor tried to load this Preview Level at startup, it crashed.
The fix is very easy though. We just need to go to the project’s Save/Config/Windows directory and open EditorPerProjectUserSettings.ini. In this file we need to locate PreviewFeatureLevel and PreviewShaderFormatName and reset them to the default state as follows:
PreviewFeatureLevel=3
PreviewShaderFormatName=None
This is the equivalent of changing the Preview Rendering Level inside the Editor:
Issue #4: Identifier not matched
When we go to the Project Settings -> Platforms -> iOS we could see the provision file has the status “Identifier Not Matched”:
This is because the Bundle Identifier is not filled in yet, or it just does not match the Id we saved in the provision in the Apple Developer portal. We need to go there and make sure we typed the same App Id in Unreal.
When everything is set up correctly, Unreal highlights in green the certificate and provision that are going to be used during the packaging process. In my case, it looks like this:
Issue #5: Packaging won’t start
When we try to package the game for iOS and Unreal opens up a page in documentation or you see errors like the following, certificate and provision are not set up properly or Unreal cannot find them. It may be also caused by a missing iTunes application so please make sure to install it on your PC. Also, make sure to download iTunes from the Apple website directly, instead of the Windows Store as Apple’s version is always up to date.
These errors may also pop up when we try to build “For Distribution” but we didn’t import the distribution certificate and provision.
Always make sure: if you build for distribution use the distribution certificate, If you build for development, use the development certificate.
Issue #6: Keyset does not exist
If we are building a C++ project, we will most likely see the following error:
System.Security.Cryptography.CryptographicException: Keyset does not exist
It occurs when Unreal tries to code-sign the packaged game and it is unable to do so. This is a somewhat general error and it may appear in several different situations.
First, make sure Unreal can connect to your Mac for remote code compiling via SSH. If the remote build options are not set up, do so. If the options are set up, make sure the connection works, i.e. by pinging your Mac by IP.
Go to Project Settings -> Platforms -> iOS -> Build category -> Remote Build Options
If the connection works and you still see the error, open Unreal Editor as an administrator.
<UE5_installation_folder>\Engine\Binaries\Win64\UnrealEngine.exe
or
<UE4_installation_folder>\Engine\Binaries\Win64\UE4Editor.exe
We need to open the Editor, open our project, and start the packaging process again.
With that, the project should package successfully. We can see that in the Unreal Output Log:
Issue #7: Failed to connect to IPC Port
When we try to install the packaged game on iPhone through the IPhonePackacger and we see an error about connecting to IPC port, it means we don’t have iTunes installed on your PC:
We need to install iTunes and just try again.
Issue #8: Crash at game’s launch
As we probably all know, the first thing we see when launching your game for the first time is most likely a crash so let’s check how to extract a crash dump.
For accessing Unreal logs on iPhone we can use IPhonePackager. Just select “Advanced Tools” -> “Other Development Tools…” -> And “Backup documents…”. Then select the packaged file installed to the device earlier.
The Packager will save the logs to the IOS_Backups folder. It will be located in the project directory or next to the IPhonePackager.exe, depending on whether we chose the .uproject file for the Packager or not.
In some cases though, crash logs may not be included in the IOS_Backups folder. What we can do is try to find them in the iOS system crash dumps. When we go to Settings -> Privacy -> Analytics & Improvements -> Analytics Data, we can find a list of files with analytic data collected by the iOS. We can find the file named by our game title and the date of the crash. When we open it, we could see the system dump log describing our crash.
Unfortunately this doesn’t give us much, because all function calls are saved as memory addresses. To find out what was called we need to convert these addresses into human-readable strings. We need to symbolicate the crash.
The easiest way to do that is through XCode, but we need to connect our device directly to the Mac. I didn’t have physical access to the Mac computer, because I worked mostly remotely, so in my case I used the symbolicatecrash tool provided by the XCode.
We can look for this tool inside the Application directory by executing the following command in Mac’s terminal:
$ find /Applications/ -name symbolicatecrash
We will find several versions of it but I used the one saved in the DVTFoundation framework.
Now we need to extract the crash from our device, upload it to Mac, then use the symbolicatecrash tool to process the crash like this:
$ export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer"
$/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash ~/Downloads/ArenaWarriors-115110.ips > ArenaWarriors_Symbolicated.txt
As a result, we have a file in which the memory addresses are converted into the actual functions calls.
Be advised though that this approach will work only if we packaged the game for iOS on the same Mac we are symbolicating, and we enabled the generation of .dSYM file in the Project Settings.
Also, symbolicatecrash tool has been deprecated in XCode 13.3 and will be removed in the future. For other ways to symbolicate the crash please see the Apple documentation:
https://developer.apple.com/documentation/xcode/adding-identifiable-symbol-names-to-a-crash-report
Issue #9: Game looks bad on iPhone
When we finally get our game up and running, we may notice that it just looks bad on the iPhone. This is because Unreal used default graphic settings for a mobile app that may not be suited to our device. We can change that through Device Profiles:
By default it provides a basic set of devices so if our device is not on the list, we need to enable the Device Profile Selector plugin. In my case it’s the IOS Device Profile Selector:
The settings that are worth checking are r.MobileContentScaleFactor, and the sg-quality. The first one allows us to scale the resolution of our game to fit best the device screen resolution. Most of the time you will use the value of 2 for iOS, which is the native resolution for iPhone. The scalability settings allow us to change the specific graphic settings, i.e. VFX, foliage, shadows, or textures quality.
All default values saved in the Device Profiles should be good enough but of course feel free to change them as you wish and see what happens. Just make sure to save your work by clicking the “Save as default” button (it will save your changes in the config file). It seems obvious but it took me some time to figure out why my changes are making no effect on the device.
Also, please see the Unreal’s documentation to learn more about device profiles settings:
If we are not satisfied with the results produced by Device Profiles, there is another trick we could use – Texture compression. Basically, we can tell the UE Cooker how much the original Textures should be compressed for mobile. These settings are available in the Project Settings -> Engine category -> Cooker.
For my UE 4.27 I changed the PVRTC Compression Quality from 1 to 2 which caused better overall quality of the Textures on mobile but at the same time, it doubled the size of the packaged game.
PVRTC is the default Texture compression format for iOS devices, but starting with the iPhone 6, Apple also supports ASTC. That’s probably why the PVRTC is removed in the UE5. Also, Apple’s GPU is based on ARM architecture so make sure to select the ARM Texture Compressor.
Issue #10: Error ITMS-90161
Shortly: If a build is not packaged for distribution, don’t try to upload it to TestFlight. This is the error the Transporter app will give us if we try to upload a development game:
The error message states that we need to use the distribution provisioning profile. To do this, we need to tell Unreal that we want to package for Distribution (Pic 11).
Checking this will automatically change the Build Configuration to Shipping, but we can set it back to Development and still upload the game to Test Flight.