Unity iOS에서 현재 지원하지 않는 기능
iOS에서 크래시 버그 신고

iOS 기기 문제 해결

Unity 에디터에서는 게임이 완벽하게 동작했으나 실제 iOS 기기에서는 제대로 동작하지 않거나 심지어 아예 실행되지 않을 경우가 있습니다. 이러한 문제는 코드 또는 콘텐츠 품질과 관련이 있는 경우가 있습니다. 이 섹션에서는 가장 일반적인 시나리오에 대해 다룹니다.

게임이 잠시 후부터 반응하지 않습니다. Xcode의 상태 표시줄에 “인터럽트”라고 표시됩니다.

이 현상이 발생하는 이유는 다양합니다. 일반적인 원인은 다음과 같습니다.

  1. 초기화하지 않은 변수 등의 스크립팅 오류
  2. Thumb 컴파일한 서드파티 네이티브 라이브러리 사용. 이러한 라이브러리는 iOS SDK 링커에서 알려진 문제를 유발할 수 있으며 랜덤 충돌을 일으킬 수 있습니다.
  3. 직렬화 가능 스크립트 프로퍼티에 대해 제네릭 타입을 값 타입과 함께 파라미터로 사용(예: List<int>, List<SomeStruct>, List<SomeEnum> 등)
  4. 매니지드 코드 스트리핑 활성화시 반사 사용
  5. 네이티브 플러그인 인터페이스 내 오류(관리되는 코드 메서드 서명이 네이티브 코드 함수 서명과 일치하지 않음) XCode 디버거 콘솔의 정보를 통해 이러한 문제를 발견할 수 있는 경우가 많습니다(Xcode 메뉴: View > Debug Area > Activate Console).

Xcode 콘솔에서 "Program received signal: “SIGBUS” 또는 EXC_BAD_ACCESS 오류가 발생합니다.

이 메시지는 일반적으로 애플리케이션이 NullReferenceException을 받았을 때 iOS 기기에서 나타납니다. 문제가 발생한 지점을 알아내기 위한 방법은 두 가지가 있습니다.

매니지드 스택 추적

Unity는 NullReferenceException의 소프트웨어 기반 핸들링을 포함합니다. AOT 컴파일러는 오브젝트가 어떤 메서드나 변수에 액세스할 때마다 null 참조 여부를 빨리 확인하는 기능을 포함합니다. 이 기능은 스크립트 성능에 영향을 주므로 개발 빌드에만 포함해야 합니다(빌드 설정 다이얼로그에서 “스크립트 디버깅” 옵션 활성화). 문제가 없고 오류가 실제로는 .NET 코드에서 발생한다면 EXC_BAD_ACCESS가 더 이상 발생하지 않습니다. 그 대신 Xcode 콘솔에 .NET 예외 텍스트가 출력됩니다(또는 작성한 코드에서 이 예외를 “catch” 구문에서 처리해버릴 수도 있습니다). 일반적으로 다음과 같이 출력됩니다:

Unhandled Exception: System.NullReferenceException: A null value was found where an object instance was required.
  at DayController+$handleTimeOfDay$121+$.MoveNext () [0x0035a] in DayController.js:122

이 메시지가 의미하는 것은 이 오류가 코루틴 역할을 하는 DayController 클래스의 handleTimeOfDay 메서드에서 발생했다는 것입니다. 또한 이것이 스크립트 코드라면 보통 오류 메시지에 정확한 줄 번호가 나타납니다(예: “DayController.js:122”). 문제가 되는 줄은 예를 들어 다음과 같을 수 있습니다.

 Instantiate(_imgwww.assetBundle.mainAsset);

이 문제는 예를 들어 에셋 번들이 제대로 다운로드 되었는지 먼저 확인하지 않고 스크립트에서 에셋 번들에 액세스했을 때 발생할 수 있습니다.

네이티브 스택 추적

네이티브 스택 추적은 오류 검사에 있어 더 강력한 툴이지만, 이 방법을 사용하려면 전문 지식이 다소 필요합니다. 또한 일반적으로 이러한 네이티브(하드웨어 메모리 액세스) 폴트가 일어난 후에는 더 이상 진행할 수 없습니다. 네이티브 스택 추적을 하려면 Xcode 디버거 콘솔에 bt all 을 입력해야 합니다. 오류가 발생한 위치에 대한 힌트가 포함되어 있을 수 있으므로, 출력된 스택 트레이스를 꼼꼼히 살펴 보십시오. 다음과 같은 내용을 발견할 수도 있습니다:

...
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 ()
...

가장 먼저 메인 스레드인 “Thread 1”의 스택 트레이스를 찾아야 합니다. 스택 트레이스의 맨 첫 줄은 오류가 발생한 지점을 가리킵니다. 이 예에서 트레이스가 나타내는 바는 “OptionsMenu” 스크립트의 “Start” 메서드에서 NullReferenceException이 발생했다는 것입니다. 이 메서드 구현을 잘 살펴 보면 문제의 원인이 밝혀질 수도 있습니다. 일반적으로, NullReferenceExceptions은 Start 메서드에서 일어나며 초기화 순서에 대해 잘못된 추정이 이루어졌을 때 발생합니다. 어떤 경우에는 디버거 콘솔에 스택 트레이스의 일부만이 나타날 경우도 있습니다.

Thread 1 (thread 11523): 

1. 0 0x0062564c in start ()

이 메시지는 애플리케이션의 릴리스 빌드 중에 네이티브 심볼이 삭제되었음을 의미합니다. 다음 과정을 통해 풀 스택 트레이스를 얻을 수 있습니다.

  • 기기에서 애플리케이션을 제거합니다.
  • 모든 타겟을 클린합니다.
  • 빌드 후 실행합니다.
  • 위에서 설명한 대로 스택 트레이스를 다시 얻습니다.

Unity iOS 애플리케이션에 외부 라이브러리를 링크할 때 EXC_BAD_ACCESS가 발생하기 시작합니다.

이 현상은 보통 외부 라이브러리가 ARM Thumb 명령어 세트로 컴파일되었을 때 발생합니다. 현재 이러한 라이브러리는 Unity와 호환되지 않습니다. 이 문제는 라이브러리를 Thumb 명령어 없이 재컴파일하여 간단히 해결할 수 있습니다. 해당 라이브러리의 Xcode 프로젝트에서 다음 단계를 거치면 됩니다:

  • Xcode의 메뉴에서 “View” > “Navigators” > “Show Project Navigator” 를 선택합니다.
  • “Unity-iPhone” 프로젝트를 선택하고, “Build Settings” 탭을 활성화합니다.
  • 검색 필드에 “Other C Flags” 를 입력합니다.
  • 여기에 -mno-thumb 플래그를 추가하고 라이브러리를 재빌드합니다.

라이브러리 소스를 사용할 수 없다면 해당 라이브러리 공급자에게 thumb을 사용하지 않은 버전을 요청해야 합니다.

Xcode 콘솔에 “WARNING -> applicationDidReceiveMemoryWarning()”이라는 메시지가 나타나고 그 후 애플리케이션이 즉시 충돌합니다.

(때로는 Program received signal: “0” 과 같은 메시지가 나타날 수도 있습니다.) 이 경고 메시지는 치명적이지 않은 경우가 많으며, 그저 iOS의 메모리가 부족하므로 애플리케이션에서 메모리를 좀 해제해 달라는 요청의 의미입니다. 일반적으로 메일과 같은 백그라운드 프로세스가 메모리를 일부 해제할 것이며 작성한 애플리케이션을 계속 실행할 수 있습니다. 그러나, 이 애플리케이션이 계속 메모리를 사용하거나 추가로 요청한다면 OS에서는 결과적으로 애플리케이션을 강제종료하기 시작하며, 현재 사용 중인 애플리케이션도 그 대상이 될 수 있습니다. Apple은 어느 정도의 메모리 사용이 안전한지에 대해 명시하지 않고 있지만 경험적으로 볼 때 전체 기기 RAM(2세대 iPad의 경우 대략 200256 MB)의 50% 이하로 메모리를 사용하는 애플리케이션은 메모리 사용량 문제를 크게 겪지 않습니다. 여기서 측정해야 하는 것은 작성한 애플리케이션이 RAM을 얼마나 사용하는지입니다. 애플리케이션 메모리 사용량은 크게 세 가지로 나누어 볼 수 있습니다.

  • 애플리케이션 코드(OS는 RAM에 애플리케이션 코드를 로드하고 유지해야 하지만 그 중 일부는 꼭 필요할 경우 제거될 수 있습니다)
  • 네이티브 힙(엔진 스테이트, 에셋 등을 엔진이 RAM에 저장하여 사용합니다)
  • 매니지드 힙(Mono 런타임이 C# 또는 JavaScript 오브젝트를 유지하기 위해 사용합니다)
  • GLES 드라이버 메모리 풀: 텍스처, 프레임버퍼, 컴파일된 셰이더 등 애플리케이션 메모리 사용량은 두 가지 Xcode Instruments 툴을 통해 추적할 수 있습니다. 바로 Activity Monitor, Object Allocations, VM Tracker 입니다. Xcode Run 메뉴에서 Product > Profile 로 이동하여 원하는 툴을 선택하면 됩니다. Activity Monitor 툴은 모든 프로세스 통계를 보여 줍니다. 여기에는 애플리케이션의 RAM 전체 사용량이라고 간주할 수 있는 Real memory 도 포함되어 있습니다. 참고: OS와 기기 하드웨어 버전이 메모리 사용량 수치에 상당히 영향을 줄 수도 있으므로 서로 다른 기기에서 얻은 수치를 비교할 때에는 주의해야 합니다.

참고: 내부 프로파일러는 .NET 스크립트에서 할당한 힙만을 보여 줍니다. 전체 메모리 사용량은 위에 나타난 것처럼 Xcode Instruments를 통하여 판단할 수 있습니다. 이 수치는 애플리케이션 바이너리 파트, 일부 스탠다드 프레임워크 버퍼, Unity 엔진 내부 스테이트 버퍼, .NET 런타임 힙(내부 프로파일러에 의해 출력된 숫자), GLES 드라이버 힙, 그 외 일부 다른 것을 포함합니다.

다른 툴은 애플리케이션이 할당한 모든 내역을 보여 주며 네이티브 힙 및 매니지드 힙 통계를 모두 포함합니다(애플리케이션의 현재 상태를 확인하기 위해 Created and still living 상자도 잊지 말고 확인합니다). 여기서 중요한 통계는 Net bytes 값입니다.

메모리 사용량을 낮게 유지하려면

  • 가장 강력한 iOS 스트리핑 옵션을 사용하여 애플리케이션 바이너리 크기를 줄이고 서로 다른 .NET 라이브러리에 대한 불필요한 종속성을 피해야 합니다. 자세한 내용은 매뉴얼의 플레이어 설정플레이어 크기 최적화 페이지를 참조하십시오.
  • 콘텐츠 크기를 줄이십시오. 텍스처에는 PVRTC 압축을 사용하고 저 폴리곤 모델을 사용해야 합니다. 자세한 정보는 매뉴얼의 파일 크기 줄이기 페이지를 참조하십시오.
  • 스크립트에서 필요 이상으로 메모리를 할당하지 마십시오. 내부 프로파일러를 사용하여 mono 힙 크기와 사용량을 추적해야 합니다.
  • 참고: Unity 3.0에서 씬 로딩 구현이 상당이 변경되었으며 이제 모든 씬 에셋은 프리로딩됩니다. 이로 인해 게임 오브젝트를 인스턴스화할 때 성능이 향상되었습니다. 게임플레이 중 에셋 로딩 및 언로딩에 더 정밀한 컨트롤이 필요할 경우 Resources.LoadObject.Destroy를 사용해야 합니다.

사용 가능한 메모리 양을 OS에 쿼리하는 것은 애플리케이션 성능을 측정하는 데 있어 좋은 방법처럼 보입니다. 그러나 OS가 대량의 동적 버퍼와 캐시를 사용하기 때문에 사용 가능 메모리 통계를 신뢰하기 쉽지 않습니다. 신뢰할 수 있는 유일한 접근법은 작성한 애플리케이션의 메모리 소비량을 계속 추적하고 이를 주 기준으로 삼는 것입니다. 위에서 설명한 툴을 통해 그래프가 시간에 따라 어떻게 변하는지, 특히 새 레벨을 로드한 후의 변화에 주의를 기울이십시오.

Xcode에서 게임을 실행했을 때에는 제대로 실행되지만, 기기에서 수동으로 실행하면 첫 레벨 로드 중에 게임이 충돌합니다.

여러 가지 원인이 있을 수 있습니다. 기기 로그를 확인하여 더 구체적인 상황을 파악해야 합니다. 기기를 Mac에 연결하고 Xcode를 시작한 후 메뉴에서 Window > Organizer 를 선택해야 합니다. Organizer의 왼쪽 툴바에서 사용 중인 장치를 선택하고 “Console” 탭을 클릭한 후 최신 메시지를 꼼꼼히 리뷰해야 합니다. 또한 충돌 보고서를 확인해 볼 필요도 있습니다. 충돌 보고서를 얻는 방법은 다음 페이지에서 확인할 수 있습니다: http://developer.apple.com/iphone/library/technotes/tn2008/tn2151.html

Xcode Organizer 콘솔에 “killed by SpringBoard” 메시지가 나타납니다.

정확히 문서화되어 있지는 않으나, iOS 애플리케이션의 경우 첫 프레임을 렌더링하고 입력을 프로세싱하는 데에 시간 제한이 있습니다. 작성한 애플리케이션이 이 시간 제한을 초과하면 SpringBoard가 이 애플리케이션을 강제 종료합니다. 이 문제는 예를 들어 첫 씬이 너무 큰 애플리케이션에서 발생할 수 있습니다. 이 문제를 피하기 위해 권장할 수 있는 방법은 스플래시 화면만을 보여 주는 작은 최초 씬을 만들고 yield 를 사용하여 한두 프레임 대기하고, 그 후 실제 씬을 로딩하기 시작하는 것입니다. 다음과 같은 간단한 코드를 사용하면 됩니다.

function Start() {
    yield;
    Application.LoadLevel("Test");
}

Type.GetProperty() / Type.GetValue() 사용 시 장치에서 크래시가 발생합니다.

현재 Type.GetProperty()Type.GetValue().NET 2.0 Subset 프로파일에서만 지원됩니다. .NET API 호환성 레벨은 플레이어 설정에서 선택할 수 있습니다.

참고: Type.GetProperty()Type.GetValue() 는 매니지드 코드 스트리핑과 호환되지 않을 수 있으며 제외되어야 할 수도 있습니다(이를 위해 스트리핑 프로세스 중에 직접 작성한 커스텀 스트립 불가 타입 리스트를 사용할 수도 있습니다). 자세한 내용은 iOS 플레이어 크기 최적화 가이드를 참조하십시오.

“ExecutionEngineException: Attempting to JIT compile method ‘SometType`1<SomeValueType>:.ctor ()’ while running with –aot-only.” 메시지가 발생하면서 게임이 크래시합니다.

iOS용 Mono .NET 구현은 AOT(네이티브 코드로 사전 컴파일) 기술에 기반하며 제한이 있습니다. 오직 다른 코드에서 명시적으로 사용되는 제네릭 타입 메서드(값 타입이 제네릭 파라미터로 사용됨)만을 컴파일합니다. 이러한 메서드가 반사를 통해 또는 네이티브 코드(즉, 직렬화 시스템)에서만 사용될 경우 이 메서드는 AOT 컴파일에서 제외됩니다. 더미 메서드를 스크립트 코드 어딘가에 추가하는 방식으로 AOT 컴파일러에 코드를 추가하도록 힌트를 줄 수 있습니다. 이렇게 하면 누락되는 메서드를 지목하여 사전에 컴파일되도록 할 수 있습니다.

void _unusedMethod() {
    var tmp = new SomeType<SomeValueType>();
}

참고: 값 타입은 기본 타입, enum, struct입니다.

System.Security.Cryptography와 매니지드 코드 스트리핑을 함께 사용 시 장치에서 여러 가지 크래시가 발생합니다.

.NET Cryptography 서비스는 반사에 강력히 의존하며 따라서 정적 코드 분석을 포함하는 매니지드 코드 스트리핑과 호환되지 않습니다. 경우에 따라 이러한 크래시에 대한 가장 쉬운 해결책은 System.Security.Crypography 네임스페이스 전체를 스트리핑 프로세스에서 제외하는 것입니다.

스트리핑 프로세스는 Unity 프로젝트의 Assets 폴더에 커스텀 link.xml 파일을 추가하여 커스텀화할 수 있습니다. 이렇게 하여 어떤 타입과 네임스페이스가 스트리핑 시 제외되어야 하는지 명시합니다. 자세한 내용은 iOS 플레이어 크기 최적화 가이드를 참조하십시오.

link.xml

<linker>
       <assembly fullname="mscorlib">
               <namespace fullname="System.Security.Cryptography" preserve="all"/>
       </assembly>
</linker>

System.Security.Cryptography.MD5와 매니지드 코드 스트리핑을 함께 사용 시 애플리케이션이 충돌합니다.

위에 나열한 조언을 활용하거나 또는 추가 레퍼런스를 스크립트 코드의 특정 클래스에 추가하여 해결할 수 있습니다.

object obj = new MD5CryptoServiceProvider();

“Ran out of trampolines of type 0/1/2” 런타임 오류

이 오류는 보통 재귀적 제네릭을 대량 사용할 때 발생합니다. AOT 컴파일러에 타입 0, 1, 2 trampoline을 더 많이 할당하라고 알려주는 방법을 사용할 수 있습니다. 추가 AOT 컴파일러 커맨드 라인 옵션은 플레이어 설정의 “기타 설정” 섹션에서 지정할 수 있습니다. 타입 1 trampoline의 경우 nrgctx-trampolines=ABCD 라 지정해야 합니다. 이 때 ABCD는 요구되는 새 trampoline의 수입니다(예: 4096). 타입 2 trampoline은 nimt-trampolines=ABCD, 타입 0은 ntrampolines=ABCD 으로 지정해야 합니다.

Xcode 업그레이드 후 Unity iOS 런타임이 실패하면서 다음 메시지를 보여 줍니다. “You are using Unity iPhone Basic. You are not allowed to remove the Unity splash screen from your game(Unity iPhone Basic을 사용하고 있습니다. 게임에서 Unity 스플래시 화면을 제거할 수 없습니다.)”

일부 최신 Xcode 릴리즈의 경우 PNG 압축 및 최적화 툴에 변경 사항이 있습니다. 이 변경 사항은 Unity iOS 런타임이 스플래시 화면 수정사항을 확인할 때 참값 오류를 발생시킬 수 있습니다. 이러한 문제가 발생했다면 Unity를 공개된 사용 가능 최신 버전으로 업그레이드해 보십시오. 문제가 해결되지 않으면 다음 조치를 취해 보십시오.

  • Unity에서 빌드할 때 Xcode 프로젝트를 (덧붙이는 대신) 완전히 처음부터 교체해 보십시오.

  • 이미 설치된 프로젝트를 장치에서 삭제해야 합니다.

  • Xcode에서 프로젝트를 클린하십시오 (Product->Clean)

  • Xcode의 Derived Data 폴더를 비우십시오(Xcode->Preferences->Locations) 이 문제가 여전히 해결되지 않으면 Xcode에서 PNG 재압축을 비활성화할 수 있습니다.

  • Xcode 프로젝트를 엽니다.

  • 여기서 “Unity-iPhone” 프로젝트를 선택합니다.

  • “빌드 설정” 탭을 선택합니다.

  • “PNG 파일 압축”을 찾아 NO로 설정합니다.

“iPhone/iPod Touch: application executable is missing a required architecture. At least one of the following architecture(s) must be present: armv6” 메시지가 발생하면서 앱 스토어 제출에 실패하였습니다.

위와 같은 메시지는 armv6 지원을 포함하여 이전에 제출된 적이 있는 이미 존재하는 애플리케이션을 업데이트할 때 발생할 수 있습니다. Unity 4.x와 Xcode 4.5는 armv6 플랫폼을 더 이상 지원하지 않습니다. 제출 문제를 해결하려면 Unity 플레이어 설정 에서 Target OS Version4.3 이상 버전으로 설정해야 합니다.

Unity 에디터와 Android에서는 WWW 다운로드가 제대로 작동하지만 iOS에서는 작동하지 않습니다.

가장 흔한 실수는 WWW 다운로드가 항상 개별 스레드에서 일어난다고 가정하는 것입니다. 일부 플랫폼에서는 맞는 말이지만, 당연하게 생각해서는 안 됩니다. WWW 상태를 추적하는 가장 좋은 방법은 yield 구문을 사용하거나 Update 메서드에서 상태 확인을 하는 것입니다. 이를 위해 while 루프를 사용해서는 안 됩니다.

스크립트에서 호출된 네이티브 함수를 통해 Cocoa를 사용할 때 “PlayerLoop called recursively!” 오류가 발생합니다.

UI 관련 일부 동작은 iOS가 창을 즉시 다시 그리도록 합니다(가장 흔한 예는 메인 UIWindow에 UIViewController와 함께 UIView를 추가하는 것입니다). 스크립트에서 네이티브 함수를 호출하면 Unity의 PlayerLoop에서 일어나게 되면서 PlayerLoop가 재귀 호출되는 결과가 발생합니다. 이러한 경우 performSelectorOnMainThread 메서드를 사용하되 waitUntilDone을 false로 설정하는 메서드 고려해 보아야 합니다. 이렇게 하면 iOS에게 Unity의 PlayerLoop 호출 사이에 해당 동작을 실행하도록 스케줄링하라고 알려주게 됩니다.

프로파일러 또는 디버거가 iOS 기기에서 게임이 실행되는 것을 감지하지 못합니다.

  • 개발 빌드로 빌드했는지 확인하고, (필요에 따라) “Script Debugging 활성화” 및 “프로파일러 자동 연결” 상자에 체크해야 합니다.
  • 장치에서 실행되는 애플리케이션은 UDP 포트 54997에서 225.0.0.222로 멀티캐스트 브로드캐스트를 합니다. 네트워크 설정이 이 트래픽을 허용하는지 확인해야 합니다. 그러면 프로파일러는 5500055511 범위의 포트에 있는 리모트 기기에 연결하여 장치로부터 프로파일러 데이터를 가져올 것입니다. 이 포트는 UDP 액세스를 위해 열려 있어야 합니다.

DLL 누락

애플리케이션이 에디터에서는 잘 실행되었으나 iOS 프로젝트에서는 오류가 발생한다면, 누락된 DLL이 원인일 수도 있습니다(예: I18N.dll, I19N.West.dll). 이러한 경우 이 DLL을 Unity.app에서 프로젝트의 Assets/Plugins 폴더로 복사해 보십시오. Unity app의 DLL 위치는 다음과 같습니다: Unity.app/Contents/Frameworks/Mono/lib/mono/unity 그리고 나서 빌드가 최적화될 때 DLL에 있는 클래스가 삭제되지 않도록 프로젝트의 스트리핑 레벨 역시 확인해야 합니다. iOS 스트리핑 레벨에 대한 자세한 정보는 iOS 최적화 페이지를 참조하십시오.

Xcode 디버거 콘솔이 다음 메시지를 출력합니다. ExecutionEngineException: Attempting to JIT compile method ‘(wrapper native-to-managed) Test:TestFunc (int)’ while running with –aot-only

일반적으로 이러한 메시지는 매니지드 함수 델리게이트가 네이티브 함수로 전달되었으나 애플리케이션 빌드 시 필요한 래퍼 코드가 생성되지 않았을 때 나타납니다. 어떤 메서드들이 델리게이트로서 네이티브 코드로 넘겨질지를 AOT 컴파일러에 알려주는 방법을 사용할 수 있습니다. 이렇게 하려면 “MonoPInvokeCallbackAttribute” 커스텀 속성을 추가하면 됩니다. 현재는 정적 메서드만이 델리게이트로서 네이티브 코드로 전달될 수 있습니다.

예시 코드:

using UnityEngine;
using System.Collections;
using System;
using System.Runtime.InteropServices;
using AOT;

public class NewBehaviourScript : MonoBehaviour {
    [DllImport ("__Internal")]
    private static extern void DoSomething (NoParamDelegate del1, StringParamDelegate del2);

    delegate void NoParamDelegate ();
    delegate void StringParamDelegate (string str);
    
    [MonoPInvokeCallback(typeof(NoParamDelegate))]
    public static void NoParamCallback() {
        Debug.Log ("Hello from NoParamCallback");
    }
    
    [MonoPInvokeCallback(typeof(StringParamDelegate))]
    public static void StringParamCallback(string str) {
        Debug.Log(string.Format("Hello from StringParamCallback {0}", str));
    }

    // Use this for initialization
    void Start() {
        DoSomething(NoParamCallback, StringParamCallback);
    }
}

Xcode에서 다음 컴파일 오류가 발생하였습니다. “ld : unable to insert branch island. No insertion point available. for architecture armv7”, “clang: error: linker command failed with exit code 1 (use -v to see invocation)”

이 오류는 보통 하나의 모듈에 너무 많은 코드가 있다는 의미입니다. 일반적으로 빌드에 대량의 스크립트 코드 또는 대형 외부 .NET 어셈블리가 포함된 경우 발생합니다. 그리고 스크립트 디버깅을 활성화하면 상황이 악화될 수 있습니다. 왜냐하면 이로 인해 상당한 양의 추가 명령어가 각 함수에 추가되므로, 제한에 도달하기 쉬워지기 때문입니다.

플레이어 설정에서 매니지드 코드 스트리핑을 활성화하면(특히 대형 외부 .NET 어셈블리가 연관된 경우) 이 문제 해결에 도움이 될 수 있습니다. 그러나 문제가 여전히 발생한다면 최선의 해결책은 사용자 스크립트 코드를 여러 개의 어셈블리로 분할합니다. 가장 쉬운 방법은 일부 코드를 Plugins 폴더로 옮기는 것입니다. 이 위치에 있는 코드는 다른 어셈블리에 포함됩니다. 또한 특수 폴더명이 스크립트 컴파일에 미치는 영향에 대한 정보도 확인해 보십시오.

Unity iOS에서 현재 지원하지 않는 기능
iOS에서 크래시 버그 신고