Unity 빌드 프로세스는 Unity linker라는 툴을 사용하여 관리되는 코드를 스트리핑합니다. Unity linker는 Unity에서 작동하도록 커스터마이즈된 IL Linker 버전입니다. Unity linker의 커스텀 Unity 엔진에 한정된 부분은 공개적으로 사용할 수 없습니다.
Unity linker는 관리되는 코드 스트리핑과 엔진 코드 스트리핑 프로세스의 일부에 책임이 있으며 이는 미사용 엔진 코드를 제거하는 IL2CPP 스크립트 백엔드를 통해 사용할 수 있는 별도의 프로세스입니다. 자세한 내용은 PlayerSettings.StripEngineCode]을 참조하십시오.
Unity linker는 프로젝트의 모든 어셈블리를 분석합니다. 먼저 루트 타입과 메서드, 프로퍼티, 필드를 마킹합니다. 예를 들어 씬의 게임 오브젝트에 추가한 MonoBehaviour에서 파생된 클래스는 루트 타입입니다. 다음으로 Unity linker는 식별하기 위해 마킹한 루트를 분석하여 이러한 루트가 의존하는 모든 관리되는 코드를 마킹합니다. 이와 같은 정적 분석이 끝나면 마킹되지 않은 모든 잔류 코드는 애플리케이션 코드의 실행 경로를 통해 도달할 수 없는 것으로 파악되어 어셈블리에서 삭제됩니다.
Unity 에디터는 Unity 프로젝트의 모든 씬에서 사용되는 타입이 포함된 어셈블리 리스트를 생성하여 이 리스트를 Unity linker에 전달합니다. 그런 다음 Unity linker는 해당 어셈블리, 해당 어셈블리의 모든 레퍼런스, link.xml 파일에 선언된 모든 어셈블리, AlwaysLinkAssembly 속성을 가진 모든 어셈블리를 처리합니다. 일반적으로 Unity linker는 이러한 카테고리 중 하나에 해당하지 않는 프로젝트 내 어셈블리를 처리하지 않으며 플레이어 빌드에서 이를 제외합니다.
Unity linker가 어셈블리를 처리할 때마다 어셈블리 분류, 어셈블리가 씬에서 사용되는 타입을 포함하는지 여부 및 사용자가 해당 빌드에 대해 선택한 Managed Stripping Level에 따라 일련의 규칙을 준수합니다.
이러한 규칙에서 어셈블리는 다음과 같이 분류됩니다.
Unity에서 프로젝트를 빌드하면 빌드 프로세스는 C# 코드를 CIL(Common Intermediate Language)이라는 .NET 바이트코드 포맷으로 컴파일합니다. Unity는 이러한 CIL 바이트코드를 어셈블리라고 부르는 파일로 패키징합니다. 프로젝트에서 사용하는 .NET 프레임워크 라이브러리와 플러그인의 모든 C# 라이브러리는 또한 CIL 바이트코드의 어셈블리로 미리 패키징됩니다.
Unity linker는 정적 분석을 수행하면 일련의 규칙을 따라 Unity linker가 빌드에 필요하다고 마킹한 CIL 바이트코드의 일부를 결정합니다. 루트 마킹 규칙은 Unity linker가 빌드에서 최상위 레벨의 어셈블리를 식별하고 보존하는 방법을 결정합니다. 종속성 마킹 규칙은 Unity linker가 루트 어셈블리가 의존하는 코드를 식별하고 보존하는 방법을 결정합니다.
Managed Stripping Level 프로퍼티는 Unity linker가 사용하는 규칙 세트를 변경합니다. 다음 섹션에서는 Managed Stripping Level 프로퍼티용으로 가능한 각 설정에 대한 마킹 규칙을 설명합니다.
다음 표에서는 Unity linker가 어셈블리의 상위 레벨 타입을 식별하는 방식을 설명합니다.
어셈블리 타입: | 마킹 규칙: | ||||
---|---|---|---|---|---|
Minimal | 낮음 | 중간 | 높음 | ||
.NET 클래스 & 플랫폼 SDK 및 UnityEngine 어셈블리 | 예방적 보존과 모든 link.xml에 정의된 모든 보존을 적용합니다. | 예방적 보존과 모든 link.xml에 정의된 모든 보존을 적용합니다. | 모든 link.xml 파일에 정의된 모든 보존을 적용합니다. | 모든 link.xml 파일에 정의된 모든 보존을 적용합니다. | |
씬에서 참조된 타입을 포함한 어셈블리 | 어셈블리의 모든 타입과 멤버 마킹. | 어셈블리의 모든 타입과 멤버 마킹. | 다음을 마킹합니다. • [RuntimeInitializeOnLoadMethod] 또는 [Preserve] 속성을 가진 모든 메서드•모든 link.xml 파일에 정의된 보존 •미리 컴파일된 패키지, Unity 스크립트 또는 어셈블리 정의 어셈블리의 MonoBehaviour와 ScriptableObject에서 파생된 모든 타입을 마킹 |
다음을 마킹합니다. • [RuntimeInitializeOnLoadMethod] 또는 [Preserve] 속성을 가진 모든 메서드•모든 link.xml 파일에 정의된 보존 •미리 컴파일된 패키지, Unity 스크립트 또는 어셈블리 정의 어셈블리의 MonoBehaviour와 ScriptableObject에서 파생된 모든 타입을 마킹 |
|
기타 | 어셈블리의 모든 타입과 멤버 마킹. | 다음을 마킹합니다. •모든 공용 타입과 해당 타입의 공용 멤버 • [RuntimeInitializeOnLoadMethod] 또는 [Preserve] 속성을 가진 모든 메서드• 모든 link.xml 파일에 정의된 보존 •미리 컴파일된 패키지, Unity 스크립트 또는 어셈블리 정의 어셈블리의 MonoBehaviour와 ScriptableObject에서 파생된 모든 타입 |
다음을 마킹합니다. •모든 공용 타입과 해당 타입의 공용 멤버 • [RuntimeInitializeOnLoadMethod] 또는 [Preserve] 속성을 가진 모든 메서드• 모든 link.xml 파일에 정의된 보존 •미리 컴파일된 패키지, Unity 스크립트 또는 어셈블리 정의 어셈블리의 MonoBehaviour와 ScriptableObject에서 파생된 모든 타입 |
다음 사항을 마킹합니다. • [RuntimeInitializeOnLoadMethod] 또는 [Preserve] 속성을 가진 모든 메서드•모든 link.xml 파일에 정의된 보존 •미리 컴파일된 패키지, Unity 스크립트 또는 어셈블리 정의 어셈블리의 MonoBehaviour와 ScriptableObject에서 파생된 모든 타입 |
|
테스트 |
[UnityTest] 속성이 있는 모든 메서드와 NUnit.Framework에서 정의한 속성으로 표시된 모든 메서드를 마킹합니다. |
Unity linker는 어셈블리에서 루트를 식별한 후 해당 루트가 의존하는 모든 코드를 식별해야 합니다. 다음 표에서는 Unity linker가 어셈블리의 루트 타입에 대한 의존성을 식별하는 방식을 설명합니다.
규칙 타겟 | 각 스트리핑 레벨의 행동 | ||||
---|---|---|---|---|---|
Minimal | 낮음 | 중간 | 높음 | ||
MonoBehaviour | Unity linker는 타입을 마킹할 때 MonoBehavior 타입의 모든 멤버를 마킹합니다. | ||||
ScriptableObject | Unity linker는 타입을 마킹할 때 ScriptableObject 타입의 모든 멤버를 마킹합니다. | ||||
Attributes | Unity linker가 어셈블리, 타입이나 다른 코드 구조체를 마킹할 때 Unity linker는 또한 해당 구조체의 모든 속성을 마킹합니다. | Unity linker가 어셈블리, 타입이나 다른 코드 구조체를 마킹할 때 Unity linker는 또한 해당 구조체의 모든 속성을 마킹합니다. | Unity linker가 어셈블리, 타입이나 다른 코드 구조체를 마킹할 때 속성 타입도 마킹되는 경우 Unity linker는 해당 구조체의 속성만을 마킹합니다. | Unity linker가 어셈블리, 타입이나 다른 코드 구조체를 마킹할 때 속성 타입도 마킹되는 경우 Unity linker는 해당 구조체의 속성만을 마킹합니다. | |
Debugging Attributes | 스크립트 디버깅을 활성화하면 Unity linker는 해당 멤버를 사용하는 코드 경로가 없어도 [DebuggerDisplay] 속성이 정의된 모든 멤버를 마킹합니다. |
스크립트 디버깅을 활성화하면 Unity linker는 해당 멤버를 사용하는 코드 경로가 없어도 [DebuggerDisplay] 속성이 정의된 모든 멤버를 마킹합니다. |
Unity linker는 DebuggerDisplayAttribute 및 DebuggerTypeProxyAttribute와 같은 디버깅 속성을 항상 제거합니다. | Unity linker는 DebuggerDisplayAttribute 및 DebuggerTypeProxyAttribute와 같은 디버깅 속성을 항상 제거합니다. | |
.NET Facade Class Library | 파사드 어셈블리는 런타임 시 필요하지 않기 때문에 제거합니다. |
Link.xml 파일은 자주 사용되지 않는 “features” XML 속성을 지원합니다. 예를 들어 mscorlib.dll에 내장된 mscorlib.xml 파일이 이 속성을 사용하지만, 적합한 경우 모든 link.xml 파일에서 사용할 수 있습니다.
High 스트리핑 레벨을 사용할 때 Unity linker는 현재 빌드에 대한 설정에 기반하여 지원되지 않는 기능의 보존을 제외합니다.
예를 들어 다음의 link.xml 파일은 COM을 지원하는 플랫폼에 포함된 타입의 메서드 1가지 및 모든 플랫폼의 메서드 1가지를 지원합니다.
<linker>
<assembly fullname="Foo">
<type fullname="Type1">
<!--Preserve FeatureOne on platforms that support COM-->
<method signature="System.Void FeatureOne()" feature="com"/>
<!--Preserve FeatureTwo on all platforms-->
<method signature="System.Void FeatureTwo()"/>
</type>
</assembly>
</linker>
High 스트리핑 레벨을 사용하면 Unity linker는 코드 크기를 추가로 축소하기 위해 메서드 바디를 편집합니다. 이 섹션에서는 Unity linker가 메서드 바디에 수행하는 주요 편집 몇 가지를 요약하여 설명합니다.
Unity linker가 .NET 클래스 라이브러리 어셈블리의 메서드 바디만 편집합니다. 메서드 바디 편집 후에는 어셈블리의 소스 코드가 더 이상 어셈블리의 컴파일된 코드와 일치하지 않으므로 디버깅이 더 어려워질 수 있습니다.
다음 리스트에서는 Unity linker가 메서드 바디를 편집하기 위해 수행할 수 있는 행동을 설명합니다.