티스토리 뷰

## 개요

개발을 할때 보통 전처리기 지시문(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

 

조건부 컴파일 - Unity 매뉴얼

Unity의 C# 언어 지원에는 지시문의 사용이 포함되어 있어서 특정 스크립팅 심볼이 정의됨 또는 정의되지 않음에 따라 컴파일에서 코드를 선택적으로 포함하거나 제외할 수 있습니다.

docs.unity3d.com

https://docs.unity3d.com/ScriptReference/Debug-isDebugBuild.html

 

Unity - Scripting API: Debug.isDebugBuild

If it is checked isDebugBuild will be true. In the editor isDebugBuild always returns true. It is recommended to remove all calls to Debug.Log when deploying a game, this way you can easily deploy beta builds with debug prints and final builds without.

docs.unity3d.com

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/preprocessor-directives

 

C# preprocessor directives

Learn the different C# preprocessor directives that control conditional compilation, warnings, nullable analysis, and more

learn.microsoft.com

https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.conditionalattribute

 

ConditionalAttribute Class (System.Diagnostics)

Indicates to compilers that a method call or attribute should be ignored unless a specified conditional compilation symbol is defined.

learn.microsoft.com

https://andrewlock.net/conditional-compilation-for-ignoring-method-calls-with-the-conditionalattribute/

 

Conditional compilation for ignoring method calls with the ConditionalAttribute

In this post I describe conditional compilation using

andrewlock.net

https://kan-kikuchi.hatenablog.com/entry/DEVELOPMENT_BUILD_DEBUG

 

開発用ビルド時に有効になるDEVELOPMENT_BUILDとDEBUGの違い【Unity】 - (:3[kanのメモ帳]

この記事でのバージョン Unity 2021.3.1f1 はじめに ゲームのデバッグ用の機能等を実装したいが、リリース時にはユーザから見えない(使えない)ようにしたい、という事がよくあります。 そんな

kan-kikuchi.hatenablog.com

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
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
글 보관함