Version: Unity 6.0 (6000.0)
언어 : 한국어
Linux IL2CPP 크로스 컴파일러
Burst compilation

스크립팅 제약

Unity는 지원되는 모든 플랫폼에서 공통 스크립팅 API와 환경을 제공합니다. 하지만 일부 플랫폼에는 고유한 제한 사항이 있습니다. 이러한 제한 사항을 이해할 수 있도록 다음 표에 각 플랫폼 및 스크립팅 백엔드에 적용되는 제한 사항을 정리했습니다.

플랫폼(스크립팅 백엔드) Ahead-of-time 컴파일 스레드 지원
Android(IL2CPP) 지원 지원
Android(Mono) 지원 안 함 지원
iOS(IL2CPP) 지원 지원
스탠드얼론(IL2CPP) 지원 지원
스탠드얼론(Mono) 지원 안 함 지원
유니버설 Windows 플랫폼(IL2CPP) 지원 지원
웹(IL2CPP) 지원 지원 안 함

AOT(Ahead-of-time) 컴파일

일부 플랫폼은 런타임 코드 생성을 허용하지 않습니다. 타겟 기기의 JIT(Just-In-Time) 컴파일에 의존하는 관리되는 코드는 모두 실패합니다. 그러므로 모든 관리되는 코드를 AOT(Ahead-of-Time) 컴파일해야 합니다. 이 차이가 중요하지 않은 경우가 많지만, 몇몇 특정한 경우에는 AOT 플랫폼을 추가로 고려해야 합니다.

반사

Unity는 AOT 플랫폼에서 반사를 지원합니다. 하지만 이 컴파일러가 반사를 통해 코드가 사용되었음을 추론할 수 없는 경우 런타임 시 코드가 존재하지 않을 수 있습니다. 자세한 내용은 관리되는 코드 스트리핑을 참조하십시오.

System.Reflection.Emit

AOT 플랫폼은 System.Reflection.Emit 네임스페이스의 메서드 중 어떤 것도 구현할 수 없습니다.

직렬화

AOT 플랫폼은 반사를 사용하므로 직렬화와 역직렬화 문제가 발생할 수 있습니다. 직렬화 또는 역직렬화의 일부인 반사를 통해서만 유형 또는 메서드가 사용되는 경우, AOT 컴파일러는 해당 유형이나 메서드가 필요로 하는 코드를 감지할 수 없습니다.

일반 유형 및 메서드

일반 유형 및 메서드의 경우, 다른 일반 인스턴스에 다른 코드가 필요할 수 있으므로 컴파일러가 어떤 일반 인스턴스를 사용할지 결정해야 합니다. 예를 들어, List<int>의 코드는 List<double>의 코드와 다릅니다. 그러나 IL2CPP는 레퍼런스 유형의 용도에 대한 코드를 공유하므로 List<object>List<string>에 동일한 코드가 사용됩니다.

다음과 같은 경우 IL2CPP가 컴파일 시간을 찾지 못한 일반 유형 및 메서드를 참조할 수 있습니다.

  1. 런타임 시 새 일반 인스턴스 생성: Activator.CreateInstance(typeof(SomeGenericType<>).MakeGenericType(someType));
  2. 일반 인스턴스에서 정적 메서드 호출: typeof(SomeGenericType<>).MakeGenericType(someType)).GetMethod(“AMethod”).Invoke(null, null);
  3. 정적 일반 메서드 호출: typeof(SomeType).GetMethod(“GenericMethod”).MakeGenericMethod(someType).Invoke(null, null);
  4. 컴파일 시점에 유추할 수 없는 일반 가상 함수에 대한 일부 호출
  5. 깊게 중첩된 일반 값 유형(예: Struct<Struct<Struct<...<Struct<int>>>>)이 있는 호출.

이러한 사례를 지원하기 위해 IL2CPP는 모든 타입 파라미터와 함께 작동하는 일반 코드를 생성합니다. 하지만 이 코드는 유형의 크기나 레퍼런스 또는 값 유형인지에 대한 가정을 할 수 없기 때문에 속도가 느립니다. 더 빠른 일반 메서드가 생성되도록 하려면 다음 단계를 따르십시오.

  • 일반 인자가 항상 레퍼런스 유형인 경우 where: class 제약 조건을 추가합니다. 그러면 IL2CPP가 레퍼런스 유형 공유를 사용하여 성능 저하를 일으키지 않는 폴백 메서드를 생성합니다.
  • 일반 인자가 항상 값 유형인 경우 where: struct 제약 조건을 추가합니다. 이렇게 하면 일부 최적화가 가능하지만 값 유형의 크기가 다를 수 있으므로 코드가 여전히 느려집니다.
  • UsedOnlyForAOTCodeGeneration이라는 메서드를 생성하고 IL2CPP가 생성할 일반 유형 및 메서드에 대한 레퍼런스를 추가합니다. 이 메서드는 호출하지 않아도 되며, 호출해서는 안 될 수도 있습니다. 아래 예시는 GenericType<MyStruct>에 대한 전문화가 생성되도록 합니다.
public void UsedOnlyForAOTCodeGeneration()
{
    // Ensure that IL2CPP will create code for MyGenericStruct
    // using MyStruct as an argument.
    new GenericType<MyStruct>();

    // Ensure that IL2CPP will create code for SomeType.GenericMethod
    // using MyStruct as an argument.
    new SomeType().GenericMethod<MyStruct>();

    public void OnMessage<T>(T value) 
    {
        Debug.LogFormat("Message value: {0}", value);
    }

    // Include an exception so we can be sure to know if this
    // method is ever called.
    throw new InvalidOperationException(
        "This method is used for AOT code generation only. " +
        "Do not call it at runtime.");
}

‘Faster (smaller) builds’ 설정이 활성화되면 전체 공유 가능한 일반 코드 버전 하나만 컴파일됩니다. 이렇게 되면 생성되는 메서드의 수가 줄어들고 컴파일 시간과 빌드 크기가 줄어들지만 런타임 성능이 저하됩니다.

네이티브 코드에서 관리되는 메서드 호출

네이티브 코드에서 호출될 수 있도록 C 함수 포인터로 마셜링해야 하는 관리되는 메서드는 AOT 플랫폼에서 몇 가지 제약 사항이 적용됩니다.

  • 관리되는 메서드는 정적 메서드여야 합니다.
  • 관리되는 메서드에는 [MonoPInvokeCallback] 속성이 있어야 합니다.
  • 관리되는 메서드가 일반 메서드인 경우 지원해야 하는 일반 전문화를 지정하기 위해 [MonoPInvokeCallback(Type)] 오버로드를 사용해야 할 수 있습니다. 이 경우 유형은 올바른 수의 일반 인자가 포함된 일반 인스턴스여야 합니다. 다음과 같이 메서드에 여러 [MonoPInvokeCallback] 속성을 가질 수 있습니다.
// Generates reverse P/Invoke wrappers for NameOf<long> and NameOf<int>
// Note that the types are only used to indicate the generic arguments.
[MonoPInvokeCallback(typeof(Action<long>))]
[MonoPInvokeCallback(typeof(Action<int>))]
private static string NameOfT<T>(T item) 
{
    return typeof(T).Name;
}

스레드 미지원

일부 플랫폼은 스레드 사용을 지원하지 않으므로 런타임 시 System.Threading 네임스페이스를 사용하는 관리되는 코드가 실패합니다. 또한 .NET 클래스 라이브러리의 일부는 암시적으로 스레드에 의존합니다. 자주 사용되는 예는 스레드 지원에 의존하는 System.Timers.Timer 클래스입니다.

예외 필터

IL2CPP는 예외 필터를 지원하지만 IL2CPP가 C++ 예외를 사용하여 관리되는 예외를 구현하기 때문에 실행 순서 필터 문과 캐치 블록은 다릅니다. 필터가 필드에 대한 쓰기를 차단하지 않는 한 눈에 띄지 않습니다.

MarshalAs 및 FieldOffset 속성

IL2CPP는 런타임 시점에 MarshalAsFieldOffset 속성의 반사를 지원하지 않습니다. 이러한 속성은 컴파일 시 지원합니다. 적절한 플랫폼 호출 마셜링에 사용해야 합니다.

동적 키워드

IL2CPP는 C# dynamic 키워드를 지원하지 않습니다. 이 키워드에는 JIT 컴파일이 필요하며, IL2CPP에서는 불가능합니다.

Marshal.Prelink

IL2CPP는 Marshal.Prelink 또는 Marshal.PrelinkAll API 메서드를 지원하지 않습니다.

System.Diagnostics.Process API

IL2CPP는 System.Diagnostics.Process API 메서드를 지원하지 않습니다. 데스크톱 플랫폼에서 필요한 경우에는 Mono 스크립팅 백엔드를 사용하십시오.

추가 리소스

Linux IL2CPP 크로스 컴파일러
Burst compilation