티스토리 뷰
[Unity] Preprocessor directives & Conditional Compilation (전처리기 지시문 및 조건부 컴파일)
progrunman 2023. 3. 15. 17:25## 개요
개발을 할때 보통 전처리기 지시문(Preprocessor Directives)을 사용해서 디버깅용 개발빌드와 릴리즈용 배포빌드를 분리하는게 보편적이다. Unity에서도 이런 전처리기 지시문을 통한 조건부 컴파일을 지원한다.
(참고 : UNITY_EDITOR는 유니티 에디터를 통해 컴파일시에만 정의됨)
public static void ConditionalMethod()
{
#if UNITY_EDITOR
Debug.Log("UNITY_EDITOR 정의시에만 해당 메서드가 산출물에 포함됨");
#endif
}
유니티 공식문서에도 나와있듯이 특정 method 호출부도 조건부컴파일 하고 싶을때는 C# `Conditional`어트리뷰트를 사용해 아래와 같이 더 깔끔하게 사용이 가능하다. 단, 몇가지 제약사항이 존재한다.
- void를 리턴하는 method만 가능 (class는 `System.Attribute`를 상속받은 특성 class만 가능)
- 조건 연산 미지원 : `#if`, `#define`, `#endif`를 통해 조건을 정의해서 회피가능
- PlayerSettings를 통해 세팅 가능하고 파일 상단 #define은 에디터 플레이모드에 적용안됨(`InitializeOnLoad`, `InitializeOnLoadMethod`에 조건부컴파일로 분기 및 define symbol을 세팅에 밀어넣는 방법으로 설정가능)
- `Start()`, `Update()`등과 같은 Unity엔진 callback method에는 적용안됨에 유의
public static void CallerLogic()
{
ConditionalMethod(); // UNITY_EDITOR 정의시에만 해당 코드가 산출물(어셈블리)에 포함됨
}
[Conditional("UNITY_EDITOR")]
public static void ConditionalMethod()
{
Debug.Log("해당 메서드 및 코드는 항상 산출물(어셈블리)에 포함됨");
}
빌드 산출물 용량을 눈꼽만큼이라도 줄이고 싶다면 아래와 같이 조합도 가능하다.
public static void CallerLogic()
{
ConditionalMethod(); // UNITY_EDITOR 정의시에만 해당 코드가 산출물(어셈블리)에 포함됨
}
[Conditional("UNITY_EDITOR")]
public static void ConditionalMethod()
{
#if UNITY_EDITOR
Debug.Log("UNITY_EDITOR 정의시에만 해당 코드가 산출물(어셈블리)에 포함됨");
#endif
}
미리정의된 Symbol외에 사용자정의가 필요할때는
- 스크립트 파일 상단에서 `#define`을 통해 정의해서 사용하거나
- Unity 직렬화 및 compilation system에 따라 프로젝트파일(.csproj)에 추가되는 시점 문제로 스크립트 상단에 #define을 정의해도 edit time에 c# 프로젝트파일에는 심볼이 추가 안됨에 유의
- Assets폴더에 .rsp 파일을 통해 심볼 추가 (비추천)
- 유니티 에디터의 "Projects Settings > Player > Script Compilation > Scripting Define Symbols"에서도 정의 가능하다.
Unity에서 미리 정의되어 있는 Symbol들은 공식문서에서 확인 가능하며 주로 사용되는 것들은 다음과 같다.
## 디버그/릴리즈 빌드 구분
- DEVELOPMENT_BUILD : 개발용 빌드로 설정되어 런타임 플레이어에서 실행될때 정의됨(Playmode가 아님에 유의)
- 해당 symbol 정의 = Build Settings의 Development Build 체크 = `Debug.isDebugBuild = true`
- DEBUG : C#용 predefined symbol이며, 유니티 에디터 빌드 또는 Development Build시 정의됨
유니티 에디터에서 디버그/릴리즈 빌드설정은 "Build Settings > Development Build" 옵션을 통해 활성/비활성 가능하다.
다른 플랫폼에서 개발하다 넘어온 개발자들은 특히 `DEVELOPMENT_BUILD`, `DEBUG` 사용시 예상처럼 동작하지 않는것에 의아해할 수 있는데 유니티 에디터의 Serialization/Compilation 동작 관계상 네이밍을 모호하게 해놓은것 뿐이므로 주의가 필요하다.
유니티 에디터 구조상 에디터상에서 호출되는 C# 스크립트는 항상 디버그 모드로 동작하므로 C# symbol인 `DEBUG`는 에디터상에서 항상 defined 상태이며, 기기 런타임 동작시에만 디버그/릴리즈 적용이 된다고 이해하면 된다.
마찬가지로 `DEVELOPMENT_BUILD`가 의미하는바도 기기 런타임 동작에 사용되는 빌드에 디버그/릴리즈 적용이지만 에디터 상에서는 항상 non-defined 상태이다.
즉, 아래 두가지는 동일한 결과를 나타낸다.
#if (UNITY_EDITOR || DEVELOPMENT_BUILD)
// 실제 배포버전인 릴리즈 빌드(기기 런타임)에서만 무시
#endif
#if DEBUG
// 실제 배포버전인 릴리즈 빌드(기기 런타임)에서만 무시
#endif
두가지 동작이 동일하지만 유니티 공식문서에 C# `DEBUG` 사용에 대한 이야기가 없고, 차후 유니티 에디터의 C# 스크립트 연동 동작이 어떻게 수정될지 모르므로 `DEVELOPMENT_BUILD`와 `UNITY_EDITOR`를 같이 사용하는 방식이 더 안전해보인다. 다만, 왜인지 `DEVELOPMENT_BUILD`는 2021.3 기준으로 VS2022 Intellisense에 나타나지 않으나 정상동작함을 확인했다.
개인적인 추천은 따로 사용자정의 symbol을 사용하는것이다.
미리정의된 symbol들은 3rd-party나 기타 라이브러리에서 사용중일수도 있어서 사용자정의 symbol을 사용해 on/off 하는것이 휴먼에러만 없다면 가장 깔끔하다. 사용자정의 symbol은 미리정의된 symbol과의 충돌을 방지하기 위해 prefix를 추가하는것이 좋다. (e.g. COMPANY_DEBUG, COMPANY_QA, COMPANY_RELEASE)
해당 사용자정의 symbol을 사용해서 wrapper util을 작성해 놓으면 몸이 편해진다. (e.g. Logging 관련 wrapper util class)
## 플랫폼 구분
- UNITY_EDITOR : 유니티 에디터에서 동작할때 정의됨
- UNITY_STANDALONE : 스탠드얼론 플랫폼(Max OS X, Windows, Linux) 전용 컴파일링/실행 코드용 스크립팅 symbol
- UNITY_ANDROID : Android 플랫폼용 스크립팅 symbol
- UNITY_IOS : iOS 플랫폼용 컴파일링/실행 코드용 스크립팅 symbol
## 유니티 에디터 버전 구분
- UNITY_2021 : 모든 2021.Y.Z 유니티 에디터를 뜻하는 symbol
- UNITY_2021_3_OR_NEWER : 특정 버전 이상의 유니티 에디터를 뜻하는 symbol
## Unit Test (Test Framework)
- UNITY_INCLUDE_TESTS : 해당 어셈블리가 유닛테스트를 포함함을 정의 (릴리즈 빌드에서 제외)
- "The purpose of UNITY_INCLUDE_TESTS is to signal whether an assembly contains tests. The constraint is added to the asmdef for the test assembly automatically when it is created. It is used by the build system to ensure that your tests does not get included in the player build, when building normally."
이외 기타 symbol들을 필요에 따라 사용 가능하다.
## 추가사항 (개인적인 결론도출)
Unity에 디버그/릴리즈 관련된 항목 정리하자면 아래와 같다
- VS2022 솔루션 구성 : 스크립트는 Unity에디터에서 컴파일되므로 IDE 솔루션 구성을 Debug/Release로 설정하는것은 컴파일 및 빌드산출물에 영향을 주지않음
- Unity Editor 모드 : 에디터 하단 상태바 우측에서 전환 가능한 Debug/Release모드. 에디터 직렬화 compilation 수행시 스크립트에 대한 Debug/Release 구성여부와 관련이 있고 에디터의 작동모드이며 빌드산출물에 영향을 주지않음
- 프로젝트세팅의 C++ Compiler Configuration : IL2CPP 산출물의 Debug/Release 구성여부. 런칭시 Release로 전환필요.
- 빌드세팅의 Development Build : 빌드 산출물의 Debug/Release 구성여부. 런칭시 체크해제 필요.
----------------------------------------------------------------------------------------------------------------------------------------------
## 주의
유니티 에디터 2021.3 기준으로 Development Build 세팅 전환시 Debug.isDebugBuild 값에 버그가 있는듯하다.
체크 <-> 체크해제간 전환 후 빌드시 Clean Build를 하지않으면 Development Build가 체크상태임에도 Debug.isDebugBuild속성에 true가 아닌 false로 세팅되어있는 경우가 있다.
유니티 디버그/릴리즈 빌드 전환시 항상 Clean빌드를 해주는것이 안전할것으로 보인다.
----------------------------------------------------------------------------------------------------------------------------------------------
## References
- 책 Effective C# (Bill Wagner)
https://docs.unity3d.com/kr/current/Manual/PlatformDependentCompilation.html
https://docs.unity3d.com/ScriptReference/Debug-isDebugBuild.html
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/preprocessor-directives
https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.conditionalattribute
https://kan-kikuchi.hatenablog.com/entry/DEVELOPMENT_BUILD_DEBUG
'Game > 개발' 카테고리의 다른 글
[Unity] Addressables (v1.19.19 기준 - Editor 2021.3) (0) | 2023.03.23 |
---|---|
[Unity] Assembly Definition (어셈블리 정의) (0) | 2023.03.16 |
[Unity] 엔진의 주요 event 함수 정리 (Awake(), Start(), etc) (2) | 2023.03.10 |
[Unity/C#] Singleton Pattern (싱글톤) (0) | 2023.02.14 |
[RuntimeInitializeOnLoadMethod] Unity 런타임 초기화 method 정의를 위한 attribute (0) | 2022.10.20 |
- Total
- Today
- Yesterday
- async
- Singleton
- github
- Scraping
- 코루틴
- unity
- selenium
- logging
- git
- initialize
- 비동기
- RuntimeInitializeOnLoadMethod
- await
- 유니티
- 환경설정
- gcp
- 닷넷
- 싱글톤
- .net
- Addressables
- firestore
- Visual Studio Code
- Python
- framework
- Debug
- coroutine
- VS2022
- C#
- vscode
- Custom Package
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |