Use the following information to help find solutions to common crashes and other problems when running your Unity application on iOS devices.
Note: If your issue persists after troubleshooting, refer to Report crash bugs for iOS.
The following list provides some common reasons for this issue:
List<int>
, List<SomeStruct>
, List<SomeEnum>
for serialized script properties.Information from the Xcode debugger console can often help detect these problems. Access the debugger console from View > Debug Area > Activate Console.
This message typically appears on iOS devices when your application receives a NullReferenceException
. Use native stack traces to find out where the fault occurred.
Native stack traces are a useful tool for fault investigation, but using them requires some expertise. You generally can’t continue after these hardware memory access faults happen. To access a native stack trace, type bt all
into the Xcode debugger console. Inspect the printed stack traces as they can contain information about where the error occurred. For example, a typical stack trace might look like this:
...
Thread 1 (thread 11523):
1. 0 0x006267d0 in m_OptionsMenu_Start ()
1. 1 0x002e4160 in wrapper_runtime_invoke_object_runtime_invoke_void__this___object_intptr_intptr_intptr ()
1. 2 0x00a1dd64 in mono_jit_runtime_invoke (method=0x18b63bc, obj=0x5d10cb0, params=0x0, exc=0x2fffdd34) at /Users/mantasp/work/unity/unity-mono/External/Mono/mono/mono/mini/mini.c:4487
1. 3 0x0088481c in MonoBehaviour::InvokeMethodOrCoroutineChecked ()
...
Locate the stack trace for “Thread 1”, which is the main thread. The initial lines of the stack trace will point to the place where the error occurred. In this example, the trace indicates that the NullReferenceException
happened inside the _OptionsMenu_
script’s _Start_
method. Inspecting this method implementation can help reveal the cause of the problem. Typically, NullReferenceExceptions happen inside the _Start_
method when incorrect assumptions are made about initialization order.
Sometimes only a partial stack trace is displayed in the debugger console. For example:
Thread 1 (thread 11523):
1. 0 0x0062564c in start ()
This message indicates that native symbols were stripped during the release build of the application. To investigate further, access the full stack trace using the following steps:
You might encounter a warning message like Program received signal: "0"
. This warning message is often not fatal, and indicates that iOS is low on memory. Typically, background processes like Mail will free some memory and your application can continue to run. However, if your application continues to use memory or ask for more, iOS will start terminating applications including your own. Apple doesn’t document what memory usage is safe, but observations have shown that applications using less than 50% of all device RAM don’t have major memory usage problems.
The main metric to use is how much RAM your application uses. Your application memory usage consists of the following components:
Component | Description |
---|---|
Application code | The OS needs to load and keep your application code in RAM, but some of it might be discarded if required. |
Native heap | Used by the engine to store its state and your assets in RAM. |
Managed heap | Used by your il2cppA Unity-developed scripting back-end which you can use as an alternative to Mono when building projects for some platforms. More info See in Glossary runtime to store C# objects. |
Metal memory pools | Used to store Textures, framebuffers, and compiled shadersA program that runs on the GPU. More info See in Glossary. |
You can track application memory usage in Xcode. For more information, refer to Gathering information about memory use (Apple Developer).
To keep memory usage low, use the following suggestions:
Querying the OS about the amount of free memory might seem to be the most efficient way to evaluate how well your application is performing. However, the free memory statistic is likely to be unreliable as the OS uses a lot of dynamic buffers and caches. It’s recommended to keep track of memory consumption for your application and use that as the main metric, combined with the Xcode memory tools especially after loading new scenesA Scene contains the environments and menus of your game. Think of each unique Scene file as a unique level. In each Scene, you place your environments, obstacles, and decorations, essentially designing and building your game in pieces. More info
See in Glossary.
It’s recommended to inspect the device logs to get more details. To do this, use the following steps:
You might also need to investigate crash reports. For more information, refer to Acquiring crash reports and diagnostic logs (Apple Developer).
There’s a set time limit to allow an iOS application to render the first frames and process input. If your application exceeds this limit, it is terminated by SpringBoard. For example, this can happen in an application where the size of the first scene is too large. It’s recommended to create a small initial scene with a splash screen, wait for a few frames, and then proceed to load the larger scene. To achieve this, use the following example:
IEnumerator Start() {
yield return new WaitForEndOfFrame();
// Do not forget using UnityEngine.SceneManagement directive
SceneManager.LoadScene("Test");
}
.NET Cryptography services aren’t compatible with managed code stripping. These services rely on reflection, whereas managed code stripping involves static code analysis. The stripping process can be customized by adding a custom link.xml
file to the Assets
folder of your Unity project. This specifies the types and namespaces to exclude from stripping. Exclude the System.Security.Crypography
namespace from the stripping process to help resolve this issue. For example, add the following to the link.xml
file:
<linker>
<assembly fullname="mscorlib">
<namespace fullname="System.Security.Cryptography" preserve="all"/>
</assembly>
</linker>
You can resolve this issue in the same way as outlined in the previous section, or you can add extra references to specific classes to your script code. To do this, use the following example:
object obj = new MD5CryptoServiceProvider();
Some operations within the UI(User Interface) Allows a user to interact with your application. Unity currently supports three UI systems. More info
See in Glossary will result in iOS redrawing the window immediately. The most common example is adding a UIView with a UIViewController to the main UIWindow. If calling a native function from a script, it will happen inside Unity’s PlayerLoop, resulting in the PlayerLoop being called recursively. When this occurs, you will receive the error message PlayerLoop called recursively!
. In such cases, consider using the performSelectorOnMainThread (Apple Developer) method with waitUntilDone
set to false. It will inform iOS to schedule the operation to run between Unity’s PlayerLoop calls.
To diagnose this issue, use the following suggestions:
225.0.0.222
on UDP port 54997
. Check that your network settings allow this traffic. The profiler will also make a connection to the remote device on a port in the range 55000 - 55511
to fetch profiler data from the device. These ports will need to be open for TCP access.This issue is caused when the built machine code is too large and has hit Xcode limitations. This can occur if you have lots of script code, or are using large external .NET assemblies in a build. Using the Script Debugging build setting can also add to this issue, as it creates additional instructions for each function.
To assist with this issue, in the Unity Editor navigate to Edit > Project Settings > Player > iOS and try one or more of the following options:
If the issue persists, it’s recommended to split user script code into multiple assemblies. For example, the Plugins
folder can be used to place any split code as code at this location is added to a different assembly. It’s also recommended to refer to Special folders and script compilation order for information on how special folder names affect script compilation.
Starting with Xcode version 14.3, Apple introduced the Destination Architecture option. With Destination Architecture, you can use iOS simulators on ARM-based Macs without the need to run Xcode in Rosetta simulator mode.
To view the iOS simulators, use the following steps: