어셈블리 정의 및 어셈블리 레퍼런스는 스크립트를 어셈블리로 구성할 수 있는 에셋입니다.
어셈블리는 스크립트에 의해 정의되고 다른 어셈블리에 대한 레퍼런스도 정의하는 컴파일된 클래스와 구조체가 들어 있는 C# 코드 라이브러리입니다. C#의 어셈블리에 대한 일반적인 정보는 .NET의 어셈블리를 참조하십시오.
기본적으로 Unity는 거의 모든 게임 스크립트를 사전 정의된 어셈블리인 Assembly-CSharp.dll로 컴파일합니다. (또한 Unity는 [몇 가지 더 작고 전문화된 사전 정의 어셈블리]도 생성합니다.)
이 배열은 소규모 프로젝트에 적합하지만, 프로젝트에 코드를 더 추가할 경우 몇 가지 단점이 있습니다.
어셈블리를 정의하면 코드를 구성하여 모듈성과 재사용성을 높일 수 있습니다. 프로젝트에 대해 정의하는 어셈블리의 스크립트는 더 이상 기본 어셈블리에 추가되지 않으며, 지정하는 다른 어셈블리의 스크립트에만 액세스할 수 있습니다.
위 다이어그램은 프로젝트의 코드를 여러 어셈블리로 분할하는 방법을 보여줍니다. Main은 Stuff를 참조하고 그 반대로는 참조하지 않기 때문에 Main의 코드 변경 사항은 Stuff의 코드에 영향을 주지 않습니다. 마찬가지로 Library는 다른 어셈블리에 의존하지 않으므로 다른 프로젝트의 Library에 있는 코드를 더 쉽게 재사용할 수 있습니다.
이 섹션에서는 어셈블리 정의 및 어셈블리 레퍼런스 에셋을 만들고 설정하여 프로젝트에 대해 어셈블리를 정의하는 방법에 대해 설명합니다.
참고 항목:
프로젝트 코드를 어셈블리로 구성하려면 원하는 각 어셈블리에 대한 폴더를 생성하고, 각 어셈블리에 속해야 하는 스크립트를 관련 폴더로 옮겨야 합니다. 그런 다음 [어셈블리 정의 에셋을 생성]하여 어셈블리 프로퍼티를 지정하십시오.
Unity는 어셈블리 정의 에셋이 포함된 폴더의 모든 스크립트를 가져온 후 에셋에 정의된 이름 및 기타 설정을 사용하여 어셈블리로 컴파일합니다. 또한 Unity는 자식 폴더에 자체 어셈블리 정의 또는 어셈블리 레퍼런스 에셋이 없는 경우 동일한 어셈블리의 모든 자식 폴더에도 스크립트를 포함합니다.
기존 어셈블리에 자식이 아닌 폴더의 스크립트를 포함하려면 자식이 아닌 폴더에 어셈블리 레퍼런스 에셋을 생성하고, 타겟 어셈블리를 정의하는 어셈블리 정의 에셋을 참조하도록 설정하십시오. 예를 들어 해당 폴더의 위치에 관계없이 프로젝트에 있는 모든 에디터 폴더의 스크립트를 자체 어셈블리에 결합할 수 있습니다.
Unity는 종속성에 의해 결정된 순서대로 어셈블리를 컴파일합니다. 컴파일이 수행되는 순서는 지정할 수 없습니다.
한 타입(예: 클래스 또는 구조체)이 다른 타입을 사용하는 경우 첫 번째 타입은 두 번째 타입에 종속됩니다. Unity가 스크립트를 컴파일할 때 스크립트가 종속되는 모든 타입 또는 기타 코드에 액세스할 수 있어야 합니다. 마찬가지로, 컴파일된 코드가 실행될 때 컴파일된 버전의 종속성에 액세스할 수 있어야 합니다. 두 타입이 서로 다른 어셈블리에 있는 경우 종속 타입을 포함하는 어셈블리는 종속되는 타입을 포함하는 어셈블리에 대한 레퍼런스를 선언해야 합니다.
어셈블리 정의 옵션을 사용하여 프로젝트에 사용된 어셈블리 간의 레퍼런스를 제어할 수 있습니다. 어셈블리 정의 설정에는 다음이 포함됩니다.
참고: 어셈블리 정의를 사용하여 생성된 어셈블리의 클래스는 사전 정의된 어셈블리에서 정의된 타입을 사용할 수 없습니다.
기본적으로 사전 정의된 어셈블리는 어셈블리 정의를 사용하여 생성된 어셈블리(1), 프로젝트에 플러그인으로 추가된 사전 컴파일된 어셈블리(2)를 비롯한 다른 모든 어셈블리를 참조합니다. 또한 어셈블리 정의 에셋을 사용하여 생성된 어셈블리는 모든 사전 컴파일된 어셈블리(3)를 자동으로 참조합니다.
기본 설정의 경우 사전 정의된 어셈블리의 클래스는 프로젝트의 다른 어셈블리에서 정의된 모든 타입을 사용할 수 있습니다. 마찬가지로, 어셈블리 정의 에셋을 사용하여 생성된 어셈블리는 사전 컴파일된 (플러그인) 어셈블리에서 정의된 모든 타입을 사용할 수 있습니다.
어셈블리 정의 에셋에 대한 인스펙터에서 Auto Referenced 옵션을 비활성화하여 사전 정의된 어셈블리에서 어셈블리를 참조하지 못하도록 막을 수 있습니다. Auto Referenced 옵션을 비활성화하면 어셈블리에서 코드를 변경할 때 사전 정의된 어셈블리가 다시 컴파일되지 않지만, 사전 정의된 어셈블리가 이 어셈블리의 코드를 직접 사용할 수 없습니다. [어셈블리 정의 프로퍼티]를 참조하십시오.
마찬가지로, 플러그인 에셋에 대한 플러그인 인스펙터에서 Auto Referenced 프로퍼티를 비활성화하여 플러그인 어셈블리가 자동으로 참조되지 못하게 막을 수 있습니다. 이는 사전 정의된 어셈블리, 그리고 어셈블리 정의를 사용하여 생성된 어셈블리 모두에 영향을 미칩니다. 자세한 내용은 플러그인 인스펙터를 참조하십시오.
플러그인 에 대한 Auto Referenced 를 비활성화하면 인스펙터에서 어셈블리 정의 에셋에 대해 명시적으로 레퍼런스를 설정할 수 있습니다. 에셋의 [Override References] 옵션을 활성화하고 플러그인 에 대한 레퍼런스를 추가하십시오. Assembly Definition 프로퍼티를 참조하십시오.
참고: 사전 컴파일된 어셈블리에 대한 명시적 레퍼런스는 선언할 수 없습니다. 사전 정의된 어셈블리는 자동 참조된 어셈블리의 코드만 사용할 수 있습니다.
순환 어셈블리 레퍼런스는 한 어셈블리 레퍼런스가 두 번째 어셈블리를 참조하고, 두 번째 어셈블리는 다시 첫 번째 어셈블리를 참조할 때 존재합니다. 어셈블리 간의 이러한 순환 레퍼런스는 허용되지 않으며, “순환 레퍼런스가 포함된 어셈블리가 감지되었습니다”라는 오류 메시지와 함께 보고됩니다.
일반적으로 어셈블리 간의 이러한 순환 레퍼런스는 어셈블리에서 정의된 클래스 내의 순환 레퍼런스로 인해 발생합니다. 동일한 어셈블리에 있는 클래스 간의 순환 레퍼런스에 대해 기술적으로 유효하지 않은 점은 없지만, 다른 어셈블리의 클래스 간 순환 레퍼런스는 허용되지 않습니다. 순환 레퍼런스 오류가 발생하면 코드를 리팩터링하여 순환 레퍼런스를 제거하거나 상호 참조하는 리팩터링 클래스를 동일한 어셈블리에 배치해야 합니다.
어셈블리 정의 에셋을 만들려면 다음 단계를 따르십시오.
Unity는 프로젝트의 스크립트를 다시 컴파일하여 새로운 어셈블리를 생성합니다. 작업이 완료되면 새로운 어셈블리 정의에 대한 설정을 변경할 수 있습니다.
자식 폴더의 스크립트를 포함하여 어셈블리 정의가 포함된 폴더의 스크립트는 (해당 폴더에 자체 어셈블리 정의 또는 레퍼런스 에셋이 없는 경우) 새로운 어셈블리로 컴파일되고 이전 어셈블리에서 제거됩니다.
어셈블리 정의 레퍼런스 에셋을 생성하려면 다음 단계를 따르십시오.
Project 창에서 참조된 어셈블리에 포함할 스크립트가 있는 폴더를 찾습니다.
폴더(메뉴: Assets > Create > Assembly Definition Reference)에 어셈블리 레퍼런스 에셋을 생성합니다.
에셋에 이름을 할당합니다.
Unity는 프로젝트의 스크립트를 다시 컴파일하여 새로운 어셈블리를 생성합니다. 작업이 완료되면 새로운 어셈블리 정의 레퍼런스에 대한 설정을 변경할 수 있습니다.
새로운 어셈블리 정의 레퍼런스 에셋을 선택하여 인스펙터 에서 해당 프로퍼티를 확인합니다.
타겟 어셈블리 정의 에셋을 참조하도록 Assembly Definition 프로퍼티를 설정합니다.
Apply 를 클릭합니다.
자식 폴더의 스크립트를 포함하여 어셈블리 정의 레퍼런스 에셋이 포함된 폴더의 스크립트는 (해당 폴더에 자체 어셈블리 정의 또는 레퍼런스 에셋이 없는 경우) 참조된 어셈블리로 컴파일되고 이전 어셈블리에서 제거됩니다.
특정 플랫폼에 대한 어셈블리를 생성하려면 다음 단계를 따르십시오.
어셈블리 정의 에셋을 생성합니다.
새로운 어셈블리 정의 레퍼런스 에셋을 선택하여 인스펙터 에서 해당 프로퍼티를 확인합니다.
Any Platform 옵션을 선택하고 제외할 특정 플랫폼을 선택합니다. 또는 Any Platform을 선택 해제하고 포함할 특정 플랫폼을 선택할 수도 있습니다.
Apply 를 클릭합니다.
플랫폼용 프로젝트를 빌드할 때 어셈블리는 선택된 플랫폼에 따라 포함되거나 제외됩니다.
에디터 어셈블리를 사용하면 Editor라는 최상위 폴더뿐만 아니라 프로젝트의 모든 위치에 에디터 스크립트를 배치할 수 있습니다.
프로젝트에서 에디터 코드가 포함된 어셈블리를 생성하려면 다음 단계를 따르십시오.
테스트 어셈블리를 사용하면 테스트를 작성하고 Unity TestRunner로 실행할 수 있으며, 테스트 코드를 애플리케이션과 함께 제공하는 코드와 별도로 유지할 수 있습니다. Unity는 [테스트 프레임워크 패키지]의 일부로 TestRunner를 제공합니다. 테스트 프레임워크 패키지를 설치하고 테스트 어셈블리를 생성하기 위한 지침은 [테스트 프레임워크 문서]를 참조하십시오.
다른 어셈블리의 일부인 C# 타입과 함수를 사용하려면 어셈블리 정의 에셋에서 해당 어셈블리에 대한 레퍼런스를 생성해야 합니다.
어셈블리 레퍼런스를 생성하려면 다음 단계를 따르십시오.
인스펙터 에서 프로퍼티를 확인하기 위해 레퍼런스가 필요한 어셈블리의 어셈블리 정의를 선택합니다.
Assembly Definition References 섹션에서 + 버튼을 클릭하여 새 레퍼런스를 추가합니다.
레퍼런스 리스트의 새로 생성된 슬롯에 어셈블리 정의 에셋을 할당합니다.
Use GUIDs 옵션을 활성화하면 새로운 이름을 반영하기 위해 다른 어셈블리 정의의 레퍼런스를 업데이트하지 않고도 참조된 어셈블리 정의 에셋의 파일 이름을 변경할 수 있습니다. (에셋 파일의 메타데이터 파일이 삭제되었거나, Unity 에디터 외부로 파일을 이동할 때 해당 메타데이터 파일을 함께 옮기지 않은 경우 GUID를 초기화해야 합니다.)
기본적으로 어셈블리 정의를 사용하여 생성된 프로젝트의 모든 어셈블리는 사전 컴파일된 모든 어셈블리를 자동으로 참조합니다. 이러한 자동 참조는 어셈블리의 코드가 사용되지 않더라도 사전 컴파일된 어셈블리 중 하나를 업데이트할 때 Unity가 모든 어셈블리를 다시 컴파일해야 함을 의미합니다. 이러한 추가 오버헤드를 방지하려면 자동 참조를 오버라이드하고 어셈블리가 실제로 사용하는 사전 컴파일된 라이브러리에 대한 참조만 지정하십시오.
인스펙터 에서 프로퍼티를 확인하기 위해 레퍼런스가 필요한 어셈블리의 어셈블리 정의를 선택합니다.
General 섹션에서 Override References 옵션을 활성화합니다.
Override References 를 선택하면 인스펙터 의 Assembly References 섹션을 이용할 수 있습니다.
Assembly References 섹션에서 + 버튼을 클릭하여 새 레퍼런스를 추가합니다.
빈 슬롯의 드롭다운 리스트를 사용하여 사전 컴파일된 어셈블리에 레퍼런스를 할당합니다. 리스트에는 프로젝트 빌드 설정에 현재 설정된 플랫폼에 대한 프로젝트의 사전 컴파일된 어셈블리가 모두 표시됩니다. (플러그인 인스펙터에서 사전 컴파일된 어셈블리에 대한 플랫폼 호환성을 설정하십시오.)
Apply 를 클릭합니다.
프로젝트를 빌드할 각 플랫폼에 대해 이 단계를 반복합니다.
프리 프로세서 심볼을 사용하면 어셈블리가 컴파일되고 게임 또는 애플리케이션의 빌드에 포함되는지 여부를 제어할 수 있습니다(에디터의 플레이 모드 포함). 어셈블리 정의 옵션의 Define Constraints 리스트에서 사용하려는 어셈블리에 대해 정의해야 할 심볼을 지정할 수 있습니다.
인스펙터 에서 프로퍼티를 확인할 어셈블리의 어셈블리 정의를 선택합니다.
Define Constraints 섹션에서 + 버튼을 클릭하여 제약 리스트에 새로운 심볼을 추가합니다.
심볼 이름을 입력합니다.
이름 앞에 느낌표를 붙여서 심볼을 “무효화”할 수 있습니다. 예를 들어 UNITY_WEBGL이 정의되지 않은 경우 !UNITY_WEBGL
제약은 어셈블리를 포함할 수 있습니다.
Apply 를 클릭합니다.
다음 심볼을 제약으로 사용할 수 있습니다.
스크립트에서 정의된 심볼은 제약이 충족되었는지 판단할 때 고려되지 않습니다.
자세한 내용은 제약 정의를 참조하십시오.
프로젝트가 특정한 Unity 버전이나 패키지 버전을 사용하는지에 따라 어셈블리에 다른 코드를 컴파일해야 하는 경우, Version Defines 리스트에 항목을 추가할 수 있습니다. 이 리스트는 기호가 정의되어야 하는 때에 대한 규칙을 지정합니다. 버전 번호에 대해 특정 버전이나 여러 버전으로 평가되는 논리적 표현식을 지정할 수 있습니다.
심볼을 조건부로 정의하려면 다음 단계를 따르십시오.
Inspector 에서 프로퍼티를 볼 어셈블리의 어셈블리 정의 에셋을 선택합니다.
Version Defines 섹션에서 + 버튼을 클릭하여 리스트에 항목을 추가합니다.
다음 프로퍼티를 설정합니다.
Expression outcome 은 표현식이 어느 버전으로 평가되는지 나타냅니다. 결과에 Invalid 가 표시되면 표현식 구문이 틀린 것입니다.
다음 예에서는 프로젝트가 Timeline 1.3을 사용하는 경우 USE_TIMELINE_1_3 기호를 정의하며, 프로젝트를 Unity 2021.2.0a7 이상에서 열면 USE_NEW_APIS를 정의합니다.
Apply 를 클릭합니다.
어셈블리 정의에서 정의된 심볼은 해당 정의에 대해 생성된 어셈블리의 스크립트 범위 내에만 있습니다.
Version Defines 리스트를 Define Constraints 로 사용하여 정의된 기호를 사용할 수 있습니다. 따라서 특정 패키지의 특정 버전이 프로젝트에 설치된 경우에만 어셈블리를 사용해야 함을 지정할 수 있습니다.
표현식을 사용하여 정확한 버전이나 여러 버전을 지정할 수 있습니다. Version Define 표현식은 수학적인 범위 표기법을 사용합니다.
대괄호 “[]”는 범위가 엔드포인트를 포함함을 지정합니다.
[1.3,3.4.1]
은1.3.0 <= x <= 3.4.1
로 평가됩니다
괄호 “()”는 범위가 엔드포인트를 제외함을 의미합니다.
(1.3.0,3.4)
는1.3.0 < x < 3.4.0
으로 평가됩니다
단일 표현식에서 범위 타입을 혼합할 수 있습니다.
[1.1,3.4)
는1.1.0 <= x < 3.4.0
으로 평가됩니다
(0.2.4,5.6.2-preview.2]
는0.2.4 < x <= 5.6.2.-preview.2
로 평가됩니다
대괄호 안에 단일 버전 지정자를 사용하여 정확한 버전을 지정할 수 있습니다.
[2.4.5]
는x = 2.4.5
로 평가됩니다
좀 더 빠른 방법으로는 범위 대괄호 없이 단일 버전을 입력하여 표현식에 해당 버전 이상이 포함되어 있음을 나타낼 수 있습니다.
2.1.0-preview.7
은x >= 2.1.0-preview.7
로 평가됩니다
참고: 표현식에서는 공백이 허용되지 않습니다. 와일드카드 문자는 지원되지 않습니다.
Unity의 현재 버전(및 어셈블리 정의를 지원하는 모든 버전)은 MAJOR.MINOR.REVISION의 세 부분으로 나뉜 버전 지정자(예: 2017.4.25f1
, 2018.4.29f1
, 2019.4.7f1
)를 사용합니다.
출시 유형 지정자의 비교 관계는 다음과 같습니다.
a < b < f = c < p < x
즉, 알파 출시는 베타 출시보다 빠르며, 베타 출시는 일반(f) 출시 또는 중국(c) 출시보다 빠릅니다. 패치 출시는 항상 개정 번호가 같은 일반 출시나 중국 출시보다 늦으며, 실험적 개정 번호는 여타 출시 유형보다 늦습니다. 실험 출시는 끝에 나중 출시일수록 커지는 번호를 사용하지 않습니다.
Unity 버전 번호는 REVISION 컴포넌트 뒤에 2019.3.0f11-Sunflower
와 같은 접미사 사용이 허용됩니다. 버전 비교 시 접미사는 무시됩니다.
예를 들어, 다음 표현식은 Unity의 모든 2017 또는 2018 버전을 포함하지만, 2019 이상 버전은 일체 포함하지 않습니다.
[2017,2019)
패키지 및 모듈 버전 지정자는 MAJOR.MINOR.PATCH-LABEL의 유의적 버전 형식을 따르는 네 부분으로 나뉩니다. 처음 세 부분은 항상 숫자이지만, 레이블은 스트링입니다. 프리뷰 상태의 Unity 패키지는 preview
또는 preview.n
이라는 스트링을 사용하며, 여기서 n > 0
입니다.
패키지 버전 번호에 대한 자세한 내용은 패키지 버전을 참조하십시오.
예를 들어, 다음 표현식은 MAJOR.MINOR 버전이 3.2 - 6.1(포함)인 모든 패키지 버전을 포함합니다.
[3.2,6.1]
C# 스크립트 중 하나가 컴파일되는 어셈블리를 식별하려면 다음 단계를 따르십시오.
Unity Project 창에서 C# 스크립트 파일을 선택하여 Inspector 창에서 해당 프로퍼티를 확인합니다.
어셈블리 파일 이름과 어셈블리 정의(존재하는 경우)는 Inspector 의 Assembly Information 섹션에 표시됩니다.
이 예제에서 선택한 스크립트는 Unity.Timeline.Editor 어셈블리 정의 에셋에서 정의된 라이브러리 파일인 Unity.Timeline.Editor.dll로 컴파일됩니다.
Unity는 폴더 내에서 특정한 특수 이름이 지정된 스크립트를 다른 폴더의 스크립트와 다르게 취급합니다. 단, 이러한 폴더는 해당 폴더 내 또는 상위 폴더에 어셈블리 정의 에셋을 생성하면 더 이상 다르게 취급되지 않습니다. 이와 같은 변화는 Editor 폴더를 사용할 때 가장 잘 알아볼 수 있는데, 이러한 Editor 폴더는 보통 코드 정리 방식 과 사용하는 에셋 스토어 패키지에 따라 프로젝트 전체에 걸쳐 분산되어 있습니다.
보통 Unity는 이름이 Editor인 폴더의 모든 스크립트를 이러한 스크립트의 위치와는 상관없이 사전 정의된 Assembly-CSharp-Editor 어셈블리에 컴파일합니다. 단, 하위 폴더 중 Editor 폴더가 있는 폴더에 어셈블리 정의 에셋을 생성하면 해당 에디터 스크립트가 사전 정의된 에디터 어셈블리가 아닌 어셈블리 정의에 의해 생성된 새로운 어셈블리로 전송됩니다. 이 위치는 잘못된 위치입니다. Editor 폴더를 관리하기 위해 각 Editor 폴더에서 어셈블리 정의 또는 레퍼런스 에셋을 생성하고 해당 스크립트를 하나 이상의 에디터 어셈블리에 배치할 수 있습니다. 에디터 코드용 어셈블리 생성을 참조하십시오.
어셈블리 속성을 사용하여 어셈블리에 대한 메타데이터 프로퍼티를 설정할 수 있습니다. 일반적으로 어셈블리 속성 문은 AssemblyInfo.cs 파일에 저장됩니다.
예를 들어 다음 어셈블리 속성은 몇 가지 .NET 어셈블리 메타데이터 값, InternalsVisibleTo 속성(테스트 작업 시 유용), 그리고 프로젝트를 빌드할 때 미사용 코드를 제거하는 방식에 영향을 주는 Unity 정의 [Preserve 속성]을 지정합니다.
[assembly: System.Reflection.AssemblyCompany("Bee Corp.")]
[assembly: System.Reflection.AssemblyTitle("Bee's Assembly")]
[assembly: System.Reflection.AssemblyCopyright("Copyright 2020.")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("UnitTestAssembly")]
[assembly: UnityEngine.Scripting.Preserve]
UnityEditor.Compilation 네임스페이스에서 CompilationPipeline 클래스를 사용하면 Unity가 프로젝트용으로 빌드한 모든 어셈블리에 대한 정보를 검색해서 가져올 수 있습니다. 여기에는 어셈블리 정의 에셋에 기반하여 생성된 어셈블리도 포함됩니다. 예를 들어 다음 스크립트는 CompilationPipeline 클래스를 사용하여 프로젝트의 모든 현재 플레이어 어셈블리를 나열합니다.
using UnityEditor;
using UnityEditor.Compilation;
public static class AssemblyLister
{
[MenuItem("Tools/List Player Assemblies in Console")]
public static void PrintAssemblyNames()
{
UnityEngine.Debug.Log("== Player Assemblies ==");
Assembly[] playerAssemblies =
CompilationPipeline.GetAssemblies(AssembliesType.Player);
foreach (var assembly in playerAssemblies)
{
UnityEngine.Debug.Log(assembly.name);
}
}
}