윈도우폰 유니티 포팅 팁


(이 문서는 http://unity3d.com/pages/windows/porting 에 있는 Porting tips for Windows Phone 문서를 한글화 한 것입니다. 원문의 업데이트에 따라서 이 문서도 업데이트 될 예정입니다.)

 

이 문서는 새로운 정보로 계속 업데이트 할 것이며, 현재에도 작업을 진행 중이다. 이 문서를 통해 해결되지 않는 문제가 있다면, Unity Windows Development 포럼을 참고하길 바란다: http://forum.unity3d.com/forums/50-Windows-Development

소개

이 문서는 윈도우 폰8으로 유니티 게임을 포팅할 때 도움이 될만한 상세 가이드와 코딩 샘플을 제공한다

이 문서를 최대한 활용하려면 Getting started on Windows Phone with Unity 소개 백서를 먼저 읽기를 권장한다.

샘플 코드

Sample Unity Project Github Repository 를 통해서 이 문서에서 다루는 기술적인 부분을 상당 부분 다루고 있다.

일반 작업

아래는 윈도우폰8으로 게임을 포팅할 때 만나는 일반적인 문제들이다.

  • 유니티에서앱을컴파일하기
  • 게임을로딩하기
  • 화면회전(Orientation) 지원
  • 플랫폼종속코드작성
  • 그래픽문제
  • 게임일시정지이어서하기
  • 작은메모리기기지원
  • 뒤로가기(Back) 버튼지원
  • 성능분석

작업의 복잡도에 영향을 미치는 것과 광범위하게 적용할 수 있는 주제부터 시작하여 각각을 논의하려고 한다.

앱을 유니티에서 컴파일

윈도우 폰 앱은 Mono가 아닌 .NET for Windows Phone runtime에서 구동 된다. .NET for Windows Phone 은 전체 .NET Framework의 부분 집합이며, 따라서 포팅 중에 Mono에는 (그리고 .NET의 전체에 있는) 존재하지만 .NET for Windows Phone 에는 없는 몇몇 클래스를 사용해야 할 수도 있다.

유니티 코드 안에서 컴파일 에러가 발생한다면, 크게 다음과 같은 이유일 것이다.

  • 클래스자체가없음 (예를들면 Hashtable)
  • 부족하거나지원되지않는오버로드가있음 (예를들면 String.Format)

포팅 시에는 가능한 기존 코드의 수정을 최소화 하고 싶을 것이다. 이 경우 권장되는 방법은 존재하지 않는 클래스의 경우 동일한 이름으로 클래스를 만들고, 부족하거나 지원되지 않는 오버로드의 경우 확장 메서드를 작성 하는 것이다. 이 방법은 이용하면 타 플랫폼과의 공통 코드를 최대한 유지할 수 있다: 새로운 버그가 생기는 위험을 줄이고, 유니티나 마이크로소프트가 추후 동일 타입이나 기능을 제공하면 수행했던 작업을 쉽게 되돌릴 수 있다.

부족한 타입에 대해서 세부적인 내용을 살펴 보기 전에, 컴파일과 관련 내용에 대해서 먼저 설명 하고자 한다. 유니티는 .NET으로 컴파일 하지만, Mono 컴파일러를 사용하는 데, 이 덕분에 유니티에서 윈도우폰용으로 컴파일을 수행할 때 도움이 되는 부분이 일부 있다. 따라서 유니티에서는 윈도우폰용 .NET에 포함되어 있지 않은 타입을 참조할 수 있으며, 이 타입들은 모든 폰 프로젝트가 참조하는 WinRTLegacy.dll 이라는 어셈블리 안 포함되어 있다. 유니티 4.3에는 이 어셈블리에 collection 클래스 (Hashtable, Stack, ArraryList)와 몇몇 공통 타입의 확장 부분을 포함하고 있다.

아래에 자주 사용되지만 누락되어 있는 타입과 이를 해결하는 방법에 대해서 다룰 것이다. 아래 내용이 이 문제의 전체를 포괄하지는 않는다.

컬렉션

System.Collections 네임스페이스를 살펴보면 자주 사용 하는 타입 중에 누락된 클래스가 있음을 알 수 있다. 이러한 타입에는 Hashtable, ArrayList, OrderedDictionary, SortedList, Queue, Stack 등이 있다.

이 같은 컬렉션의 대부분은 WinRTLegacy를 통해서 제공되고 있으며, 유니티는 Hashtable, Stack, ArrayList을 동일하게 만들어 가고 있다. OrderedDictionary 는 샘플 프로젝트 내에 구현되어 있다.

 

Socket 기반의 네트워킹 API

System.Net 내의 일부 네트워킹 관련 클래스들은 .NET for Windows Phone에는 존재하지 않는다. 미리 작성 해둔 샘플 프로젝트에 Windows.Networking.Socket WinRT 네임스페이스를 사용하는 System.Net.TCPClient를 거의 완전하게 구현해 두었다.

/UnityPorting/tree/master/PlatformerPlugin/MyPluginUnity/Legacy/System/Net

WinRT에는 Windows.Networking 네임스페이스를 통해서 새로운 소켓 API를 제공하고 있으며, 샘플 프로젝트의 기능을 데모수준으로 살펴보고 이를 확장하는 것이 더 좋을 수 있다.

 

다른 클래스 추가

위에서 살펴본 내용이 누락된 모든 내용을 다루지는 않는다. 하지만 자주 사용되는 타입을 대체적으로 다루고 있고, 이를 통해 게임을 포팅할 때 필요한 작업의 범위를 올바르게 판단할 수 있었으면 한다. 플러그인을 이용하는 기존 코드에 영향을 주지 않으면서 누락된 기능을 포함시키거나 구현하는 방법을 익히려면 샘플 프로젝트를 살펴보기 바란다. 이에 대한 소스 코드는 다음 프로젝트 내에 포함되어 있다.

/UnityPorting/tree/master/PlatformerApps/MyPluginUnity/Legacy

클래스나 메서드를 대체 구현하려면, 네이티브 API(Windows Runtime에 있는)가 필요할 수도 있다. 이 경우 윈도우와 유니티 사이에 상호운용에 대해서 상세하게 다루는 "플랫폼 종속 코드 작성"을 참고하기 바란다.

3rd Party Plugins

앞서 살펴본 주요 클래스 외에도, 서드파티 플러그인이 필요할 수도 있다. 몇몇 인기 있는 플러그인들(NGUI나 Toolkit2D등)은 이미 윈도우 스토어로 포팅 작업이 완료 되었다. 하지만 다른 플러그인 들은 아직 포팅 되지 않았을 수 있다.

소스 코드로 배포되는 플러그인(NGUI 같은) 을 사용한다면, 컴파일러로 대부분의 이슈를 잡을 수 있다. 바이너리로 배포되는 플러그인을 사용한다면, 이를 로드하거나 사용할 때 런타임 에러가 발생할 것이다. 플러그인이 윈도우폰이나 윈도우스토어와 호환되는 지를 알아보려면 http://scan.xamarin.com 에서 실행해 보는 것이 가장 좋은 방법이다

플러그인이 호환되지 않는다면, 플러그인 저작자에게 연락하거나 jaimer@microsoft.com 을 통해서 알려주길 바란다.

게임 로드 중 진행상황 보고

게임을 실행 했을 때, 게임이 멈추지 않고 수행 중임을 알 수 있도록 진행 상황을 보여주는 것은 중요하다.

여기에서는 XAML 프로젝트를 사용한다고 가정한다. 여기 있는 대부분의 개념은 DirectX 프로젝트에도 적용가능하나, 구현 방법은 많이 다를 것이다.

유니티에서는 윈도우 스토어/윈도우 폰에서 게임이 로딩되는 과정을 나타내는 2가지 방법을 제공한다.

  1. 스플래시스크린
  2. 확장된스플래시경험

앱 스플래시 스크린(App Splash Screen)

초기 스플래시 스크린 이미지는 OS에 의해서 보여질 것이고, 이 가이드에 따라서 구성할 수 있다.

확장 스플래시 경험(Extended Splash Experience)

윈도우폰은 OS가 유니티 씬(scene)을 호스트하는 (XAML 마크업으로 작성한) 페이지를 로드하는 동안 초기 앱 스플래시 스크린을 보여준다.

보통, 유니티 씬은 로드하는데 더 많은 시간이 걸린다. 따라서 유니티 씬이 로드되는 동안 동일한 스플레쉬 이미지에 진행률 표시줄을 같이 나타내고 싶을 것이다. 이를 확장 스플래시 경험 이라고 한다.

샘플 유니티 프로젝트는 이에 대한 기본 예제를 포함한다. 게임이 로드 되는 동안 진행률 표시줄이 포함된 스플래시 화면이 나타나고 유니티가 로딩을 마치면 화면이 사라진다.

MainPage.xaml에서 스플래시 스크린 이미지에 진행률 표시줄이 추가되어 있음을 볼 수 있다.

참고: 진행률 표시줄을 최대 값을 넘지 않도록, 최대 값을 가장 느린 디바이스에서 로드 되는 시간 보다 크게 설정해야 한다. ProgressBar를 무한 반복 형태로 지정 할 수 도 있다. – 무한 반복 형태의 진행률 표시줄은 움직이는 점으로 나타난다. 누적 진행률을 나타내는 것은 아니다.

MainPage.xaml.cs (XAML UI를 위한 코드 비하인드 파일)에서는 사용자에게 시각적인 피드백을 주려면 진행률 표시줄이 움직일 수 있도록 생성자 내에서 타이머를 시작한다.

다음으로 WindowsGateway.UnityLoaded() 이라는 유니티 쪽의 델리게이트를 할당한다. WindowsGateway는 "Writing Platform Specific Code" 절에서 자세히 설명할 것이다.

WindowsGateway.UnityLoaded() 이 발생할 때, 유니티가 로딩을 끝냈음을 나타내기 위해서 private bool 값을 설정한다. 이제 진행률 표시줄의, 타이머는 다음 틱(Tick) 이벤트에서 이를 감지하고, 게임을 보여주기 위해 진행 바를 제거한다.

참고: AppCallbacks.Initialized() 라는 이벤트도 있다. 하지만 이는 매우 일찍 발생하는 경향이 있다. 대부분의 게임에서는 게임을 플레이 할 수 있게 되면, 명시적으로 이를 앱에게 알려주도록 로딩 방식을 제어하는 것이 필요하다.

 

화면 방향 지원

앱의 화면 방향이 변하면, 특별한 작업을 하지 않아도 유니티가 자동으로 이를 처리한다. 언제든 유니티의 Screen.orientation 을 살펴볼 수 있다.

그러나 대부분의 게임은 세로 혹은 가로 방향으로 고정되어서 구동된다. MainPage.xaml에서 메인 PhoneApplicationPage 엘리먼트의 다음 애트리뷰트를 설정하는 것으로 쉽게 고정할 수 있기는 하다.

이 경우 회전된 SplashScreenImage.jpg(세로 화면에서 나타나는 스플레쉬 화면)을 갖고 있어야 한다. 그리고 확장 스플래시 경험을 위해서 가로 방향의 이미지도 갖고 있어야 한다.

이 접근 방법은 유니티 샘플 프로젝트에서 볼 수 있다. 루트(메인 앱 스플래시 페이지)의 SplashScreenImage.jpg 과 (확장 스플래시 경험에서 보이는) SplashScreenImageLandscapeLeft.jpg을 참고하라.

스플래시 스크린을 떠나서, 가로 방향을 지원하기 위해서 해야 할 작업의 분량은 포팅하려는 게임의 종류에 따라 다르다. 설사 게임이 세로 중심으로 개발되었더라도, 스크린 메뉴 아이템의 변경에 따라서 게임 안에서의 카메라 위치를 상대적으로 약간 조정해야 할 수도 있다.

플랫폼 종속 코드 작성

코드를 포팅하는 것은 게임을 제작하는 일의 일부이다. 앱내 결제나 설정 등의 작업을 구현하려면 플랫폼 API를 사용해야 할 수도 있다

유니티 스크립트 안에서 플랫폼 API를 호출하는 방법에는 몇 가지 서로 다른 방법들이 존재한다.

유니티 스크립트와 호스트 프로세스 양쪽에서 .NET이 구동되기 때문에, 유니티 엔진과 앱 사이에서 통신을 수행할 수 있다. 이 기술은 매우 단순하지만 타입과 노출할 수 있는 통신 방식에 따라 제한이 있다.

더 시간을 투자하면 재활용성이 높고 여러 타입에서 사용할 수 있으며, 참조 가능한 API 형태로 유니티 플러그인을 만들 수 있다. 이 기법은 더 많은 노력이 필요하다.

이 두 가지 기술은 예제를 통해서 알아볼 것이다.! 유니티 샘플 프로젝트를 살펴보면 /Assets/Scripts/Windows/WindowsGateway.cs 내에서 클래스를 찾을 수 있는데, 이 클래스는 윈도우 스토어와 유니티 사이에 통신을 제공한다. 이 클래스에는 직접 통신 방식과 플러그인을 통한 통신 방식을 둘다 포함하고 있어서 유니티 게임 코드와 윈도우 종속 코드간의 통신을 추상화 하고 있다.

직접 통신

직접 통신은 매우 단순한 접근 방식을 취한다. 유니티 스크립트 안에서 호스트는 참조와 접근할 수 있는 클래스를 생성할 수 있다.

예를 들면, WindowsGateway는 Action을 노출한다. (action은 파라미터가 없는 void delegate 이다):

비주얼스튜디오의 호스트 코드 안에서 코드를 직접 호출할 수 있다:

이러한 방식은 기술적으로 매우 단순하고 대부분 "콜백 중심"으로 이루어진다. 아래에 이러한 방식을 구현하기 위해 알아야 할 세부 단계를 설명하였다.

컴파일러 디렉티브 사용

#if UNITY_WP8 && !UNITY_EDITOR 를 사용해서 게이트웨이 클래스와 코드와 이를 사용하는 코드가 윈도우 폰이 구동되는 컨텍스트 안에서 수행된다.

참고: UNITY_WINRT를 사용해서 윈도우 스토어 앱과 윈도우 폰8앱을 모두 지원할 수도 있다. 윈도우폰8만을 지원하기 위해서 UNITY_WP8를 사용할 수도 있다.

윈도우 폰 앱에서 유니티 호출 먀살링하기

유니티 쪽을 호출 할 때에는 앱 스레드로 마샬링을 해줘야 함을 명심하기 바란다.

반대로 윈도우폰 쪽으로 호출을 하기 위해서는 Dispatcher를 사용하고, 유니티 앱 스레드를 윈도우폰 UI 스레드로 변경해야 한다. 예를 들면 앱 내부 결제를 위해서 윈도우폰 API 를 사용할 때에는 예외가 발생하는 것을 피하기 위해서 UI 스레드를 사용해야 한다.

단순하게 유지하고 메모리 누수를 없애라

앱과 유니티 사이에 직접 연결을 위해서 종종 콜백을 사용한다. 몇몇 인스턴스에서 (멀티캐스트 델리게이트 같은) 이벤트가 필요할 수 있지만 흔한 경우는 아니다. 작업을 단순화 하기 위해서 Func이나 Action을 사용한다.

특히 메모리 누수가 발생하지 않도록 조심해야 한다. 호스트가 씬(scene)을 잡고 있다면, 많은 메모리를 사용하고 있을 수 있다. 이런 상황에서 Func 이나 이벤트를 사용할 때는 메모리 누수가 발생하지 않도록 주의해야 한다.
코드에서 간단히 참조를 해제하거나 이벤트에 대한 구독을 해제할 수 없다면, 약한 참조(Weak Reference) 같은 테크닉을 사용해 볼 수 있다. 핵심을 보여주기 위해서 샘플은 단순하게 구현했다.

윈도우 폰 유니티 플러그 인

플러그인은 (.NET에서는 어셈블리라고도 불리는) 바이너리 dll이다. 유니티 스크립트 안에서 이를 참조할 수 있다. 원칙적으로 플랫폼 종속 코드가 있는 플러그인은 유니티 스크립트에서 직접 참조할 수 없다. 왜냐하면 유니티는 WinRT API를 직접 참조하지 않기 때문이다. 그리고 플러그인은 재사용 가능한 컴포넌트로 로직을 캡슐화하는데 사용될 수 있다.

윈도우 스토어와 윈도우폰8용 유니티 플러그인을 만드는 가이드는 아래를 참조하기 바란다.
https://docs.unity3d.com/Documentation/Manual/windowsstore-plugins.html
http://docs.unity3d.com/Documentation/Manual/wp8-plugins-guide-csharp.html

"MyPlugin"이라고 불리는 예제 플러그인은 유니티 샘플 프로젝트 솔루션의 일부로 제공된다. 여기서는 유니티가 이 플러그인을 어떻게 사용하는지 그 구조와 세부 사항을 살펴보고자 한다.

윈도우 스토어 앱과 함께 세 개의 관련 프로젝트가 있다.

  • MyPluginUnity - .Net 3.5 클래스라이브러리
  • MyPluginWindows윈도우 8.1 클래스라이브러리
  • MyPluginWP8윈도우폰 8 클래스라이브러리(윈도우8위한)

각각의 플러그인 프로젝트는 MyPlugin.dll이름의 어셈블리를 결과물로 내놓는다. 같은 이름을 갖는 것은 유니티의 요구사항 이다. 빌드 이후에 post 빌드 스크립트를 이용하여 유니티에서 미리 정해둔 폴더의 구조에 맞추어 어셈블리를 자동으로 복사한다.

  • /Assets/Plugins/MyPlugin.dll MyPluginUnity의해서생성되며유니티에디터내에서사용될것이다.
  • /Assets/Plugins/Metro/MyPlugin.dll MyPluginWindows의해서생성되며, Visual Studio윈도우스토어앱에서참조하고런타임시에사용된다.
  • /Assets/Plugins/WP8/MyPlugin.dll MyPluginWP8의해서추가되며, Visual Studio윈도우스토어앱에서참조하고런타임시에사용된다.

샘플 플러그인은 ShowShareUI()를 허용하고, 이는 /Assets/Scripts/ShareManager.cs 유니티 스크립트 안에서 찾을 수 있다.

이는 윈도우 8과 윈도우폰8에서 모두 동작할 수 있음에 주목하기 바란다.

각 플러그인을 위한 코드를 조사하거나 샘플을 돌려보면, 구현이 윈도우폰과 윈도우8 , 유니티 코드 안에서 다른 것을 확인 할 수 있다. 하지만 이는 동일한 호출이고 하나의 코드 호출 경로이다.

에디터 경험을 위해 MyPluginUnity에 의해서 생성된 어셈블리는 유니티 스크립트가 작성되기 위해서 동일한 바이너리 계약(같은 API)을 노출해야 한다. 대부분 에디터 dll의 함수(functions)는 동작을 하지 않거나 아무것도 하지 않을 것이다. 그러나 유니티 스크립트가 컴파일 되기 위해서 있어야만 한다. 교환은 나중에 일어난다. 그리고 에디터 dll 없이 프로젝트는 컴파일 되지 않는다.

윈도우폰 플러그인에서 호출을 마샬링 하기

플러그인에서는 유니티 플레이어에 접근할 수 없다. 따라서 UI와 유니티 앱 스레드 간에 마샬링을 수행 해야만 한다. 다행히 샘플 프로젝트에서 이 같은 작업이 되어 있다.

MyPluginWP8 윈도우 스토어 플러그인 프로젝트를 살펴보면 Dispatcher 클래스를 사용하고 있음을 확인할 수 있는데, 이 클래스는 앱과 UI 스레드에 접근할 수 있는 한 쌍의 정적 프로퍼티를 갖고 있다.

플러그인 내부에서 이 작업을 수행하려면, 앱 내부에서 이 프로퍼티를 설정해야 한다. 이 업을 수행하기에 가장 좋은 위치는 App.xaml.cs에서 유니티가 초기화 된 이후다.

여기서 UIDispatcher와 AppDispatcher를 설정함으로써, 앱 전반에 걸쳐 동일한 마샬링 방법을 사용할 수 있다.

유니티 측을 호출할 때에는 항상 앱 스레드로 마셜링 해야 함에 주의하여야 한다. 다음 예제는 이 러한 접근 방식을 사용할 경우 플러그인 내에서 유니티를 호출하는 예제이다.

반대의 경우에는 플러그인 내에서 UI 스레드를 가져오기 위해서 InvokeOnUIThread()를 사용한다. 예를 들면 샘플에서 페이스북 로그인 창을 띄우려면 예외가 발생하지 않도록 다음과 같이 코르르 작성해야 한다.

플러그인 혹은 의존성 주입

두 가지 모두 유효한 방식이다. 둘 줄 어느 쪽이 낫다고 말할 수는 없다. 작성하는 앱이나 플랫폼 종속 코드의 형식에 따라 둘 중 하나를 선택적으로 사용하면 된다.

 

플러그인(Plugins)

  • 재활용가능한플랫폼종속코드를바이너리로캡슐화하는데최적
  • 일반적으로추상화된시나리오에적합
  • 설정과유지보수에조금시간이많이소요됨
  • 유니티에서플랫폼종속코드를다루는방식으로추천

의존성 주입(Dependency Injection)

  • 빠르게이해하고구현가능
  • 단순하게유니티스크립트와클래스에직접추가
  • 앱과유니티간에양방향통신지원
  • 재활용에좋지않음. 프로젝트간에복사붙여넣기를유발할있음

그래픽 문제

모든 윈도우폰 8 디바이스는 마이크로소프트 Direct3D 11의 level 9_3 기능 레벨을 지원하는 GPU를 갖고 있다 다음은 커스텀 쉐이더를 사용할 경우 직면할 수 있는 문제들이다:

쉐이더 스테이지들을 거친 모든 변수들에 대해 시멘틱(semantics)가 필요하다.

아래 예제는 에러를 생성한다:

struct vertOut {
float4 pos:SV_POSITION;
float4 scrPos;         //ERROR! no semantic
};

고치는 방법은 간단하다.

struct vertOut {
float4 pos:SV_POSITION;
float4 scrPos: TEXCOORD0; // <-- FIX! add semantic.
};

일반적인 목적의 시멘틱의 경우 TEXCOORD[n] 사용하는 일반적이다. 이는 아무 것도 할당 되지 않았다면 좋은 방법이다.

안개(Fog)가 구현되지 않았다.

수동으로 이를 구현해야 할 수 있다. 유니티는 http://files.unity3d.com/tomas/Metro/Examples/MyCustomFog.shader 에서 안개 샘플 쉐이더를 제공한다.

윈도우와 폰에서 직면하게 되는 몇몇 이슈를 재현하고 있는 샘플 유니티 프로젝트 코드 베이스는 다음에서 살펴볼 수 있다. /UnityPorting/blob/master/Resources/ShaderIssueExamples.unitypackage

  • MissingSemanticShader.shader 은 없는 시멘틱 이슈를 보여준다. 이 문제를 보려면 Visual Studio에서 빌드하고 실행해야 한다. 쉐이더 코드는 어떻게 해결하는지를 보여 주려고 주석 처리 해 두었다.
  • MyCustomFogLinear.shaderMyCustomFogExp2.shader 는 쉐이더 코드에서 안개를 구현하는 두 가지 방법을 보여준다. 이는 각각 Liner와 Exp2Fog로 하드코딩 되어 있다.

일시 정지 및 이어서 하기

윈도우 폰의 앱 모델은 하나의 포어그라운드(foreground) 앱(눈에 보이는)만을 허용 한다. 포어그라운드 앱은 대부분의 OS 자원(메모리, CPU, 네트워크)에 접근할 수 있고, 빠른 앱 전환을 위해서 OS는 사용자가 최근에 사용했던 앱들 중 메모리에서 명시적으로 종료하지 않았던 앱들을 보관하고 있다. 이 앱 모델에 대한 설명은 "App activation and deactivation for Windows Phone"를 살펴보기 바란다.

포팅 편의를 최대화 하기 위해서, 유니티는 윈도우폰 이벤트를 잘 알려진 유니티 이벤트로 매핑한다. 다음 샘플에서는 윈도우폰에서 유니티 이벤트와 연관되어 발생하는 이벤트의 순서를 보여준다:

Action 

윈도우폰 이벤트

유니티 이벤트/오버라이드

수행해야 할 작업은?

사용자가 게임을
실행하기 위해
타일을 탭

Launching

 

 

Activated (with e.IsApplica
tionInstancePreserved to false)

Awake ()
OnApplicationPause(true)

OnApplicationFocus()

Start ()

게임을 시작. 새로 시작 (처음 부터, 이어서 하는 것이 아님)

사용자가 다른
앱으로 전환하기
위해 윈도우 버튼을 탭

Deactivated

OnApplicationPause(true)

세션 사이에 유지해야 하는 모든 상태를 저장.
앱이 한번 비활성화되면, OS에 의해서 종료될 수 있으며, 프로세스는 호출되지 않음. 모든 네트워크 호출은 취소됨; 게임은 CPU 를 사용하지 못함

사용자가 게임으로
돌아옴(작업
관리자나 뒤로가기
버튼을 눌러서)

Activated (with e.IsApplica
tionInstancePreserved to true)

OnApplicationPause(false)

게임을 이어서 실행
모든 리소스를 다시 사용할 수 있음

사용자의 전화가
울리거나 푸쉬
통지가 와서 화면의
일부를 가림(하지만
사용자는 앱으로
전환하지 않음)

Obscured 

OnApplicationPause(true)

게임을 일시 멈춤.
네트워크 호출은 취소되지 않으며 게임은 여전히 CPU를 사용하고 있음. 메모리 내에 존재하며 활성화 상태를 유지함

통지 UI가 사라짐.
사용자가 이를
무시함

Unobscured 

OnApplicationPause(false)  

게임을 이어서 실행

사용자가 게임이나
앱을 종료하기
위해서 뒤로 가기
버튼을 클릭 함

Closing  

OnApplicationQuit

상태를 저장하고 게임을 빠져 나옴. 다음 번에 게임이 시작되면 메인
페이지로부터 시작됨. 완전히 다시 수행.

가능한한 빨리 상태를 저장해야만 유니티 이벤트로의 기본 매핑이 정상 동작할 것이다. 만약 좀 더 최적화를 수행하고 싶다면, App.xaml.cs에 있는 모든 이벤트들과 이를 구독하고 있는 유니티 코드를 살펴서 C# 측의 이벤트 핸들러에 로직을 추가하고 게임 코드와 통신할 수 있는 플러그인을 사용하면 된다.

추가적으로, 윈도우 폰용 게임은 "Fast App Resume"이란 기능을 지원해야 하는 데 이 기능은 시작 화면의 타일이나 메인 앱 리스트 아이콘을 선택하여 앱을 수행했을 때, 동일 앱이 앞서 일시 중지된 상황일 경우, 이를 이어서 수행 하는 것을 말한다.

이러한 기능을 구현하려면 /Properties/WMAppManifext.xml 파일을 열고, 아래와 같이 볼드체로 표시한 속성을 추가하기만 하면 된다:

메모리가 적은 디바이스 지원

메모리는 여러 가지 구성이 가능하다: WVGA 디바이스용 512MB, 720p 디바이스용 최소 1GB 램. 노키아 1020 같은 최신 폰은 최대 2GB로 구성이 가능하다. Nokia 1020과 같은 신제품은 메모리가 2GB이다.

단일 앱이 사용할 수 있는 메모리의 크기는 OS가 제한 한다. 메모리가 적은 폰에서는 앱당 150MB 정도로 제한을 하고 있고, 메모리가 많은 폰에서는 앱당 380메가 정도로 제한을 하고 있다. 이를 위해 manifest에서 메모리 사용 방식을 명기하거나 저사양의 디바이스에서 앱이 동작하지 못하도록 설정할 수 있다.

기본 유니티 프로젝트는 윈도우폰 프로젝트의 /Properties/WMAppManifest.xml 파일에있는ID_FUNC_EXTENDED_MEM capability을 사용하는데, 이렇게 하면 메모리가 적은 디바이스에서도 180MB까지를 사용할 수 있다. ID_REQ_MEMORY_300 을 설정해서 메모리가 적은 디바이스에서는 앱을 사용할 수 없도록 할 수도 있다. App Memory Limits 문서를 살펴보면 제약사항과 capability에 대해서 좀 더 자세히 알 수 있다.

 

뒤로 가기 버튼 처리

모든윈도우폰은뒤로가기버튼을있고, 버튼이눌렸을해야하는작업에대한가이드라인이있다:

 

  • 안에서페이지네비게이션을구현했다면뒤로가기버튼을눌렀을이전페이지로돌아가야한다.
  • 모달대화창(예를들면설정또는성취물, ) 안에서뒤로가기버튼을눌렀다면, 모달창을닫야아한다.
  • 대화창이아니고페이지네비게이션의최초화면에있는상태에서(또는게임안에서페이지네비게이션을구현하지않았다면), 뒤로가기버튼을눌렀다면, 게임을종료해야한다.

뒤로 가기 버튼에 대한 처리는 안드로이드와 같은 방식을 사용한다: ESC 키를 수신처리 하면 된다. 유니티는 호스트 레벨에서 윈도우폰 뒤로 가기 버튼 탭을 ESC 키로 변환하는 작업을 수행 해 준다. 업데이트 루프 안에서 키 입력을 처리하고 이에 맞는 동작(모달 UI를 해지하거나 앱을 종료하도록 하는 등)을 수행하면 된다.

뒤로 가기 버튼을 적절하게 처리하는 것은 인증 요구사항이라는 점을 알아두자. 이를 처리하지 않으면 인증에 실패하게 된다. 유니티에서 내보낸 기본 코드는 이를 처리하지 않으므로 ESC 키에 대한 처리를 직접 수행 해야 한다. 만약 업데이트 루프 안에서 매번 ESC 키를 확인하기 위해서 CPU 시간을 낭비하고 싶지 않다면, 뒤로 가기 버튼을 눌렀을 때 항상 게임이 종료 되도록, 모달 대화창이 없는 단일 화면 게임으로 구성해야 한다. 이 때 MainPage.xaml.cs에 있는 BackKeyPress 이벤트 핸들러의 e.Cancel 선언을 주석처리 하면 된다.

디버깅 및 성능 분석

게임을 만들 때 보다 더 깊이 있게 파고들어야 하는 문제를 만날 수 있다.

이번 절에서는 앱 디버깅을 다룬다. 유니티 로그 파일에 접근하고, 유니티 프로필러를 사용해서 실시간으로 앱 성능을 분석하는 방법을 살펴볼 것이다.

앱 디버깅

앱과 유니티 C# 스크립트를 디버깅 할 때, Visual Studio를 사용할 수 있다. 이는 문제를 좁히는데 상당한 도움이 된다.

  • 폰이 PC연결되어있고언락것을확인.
  • File -> Add -> Existing Project선택하고유니티프로젝트폴더를찾은 Assembly-CSharp.csproj 파일을선택해서클릭하여, Visual Studio솔루션에유니티의 Assembly-CSharp 프로젝트를추가한다.
  • 추가적으로파일은이미유니티에의해서빌드되었으므로 Assembly-CSharp 빌드플래그를선택해제한다.
  • Project -> Properties -> Debug 아래에서디버거타입이 Managed Only (default)설정되었는지확인한다.

이제 프로젝트 또는 유니티 스크립트 파일 내에서 자유롭게 중단점을 설정하고, F5로 빌드 및 배포를 하고 앱을 실행 하고 디버깅 할 수 있다.

유니티 로그 파일(The Unity Log File)

만약 디버깅이 이슈를 해결하지 못하면, UnityPlayer.log 파일을 살펴보는 것이 유용할 수 있다. 이는 폰에 저장되어 있으므로, Windows Phone Power Tools 로 꺼내어 살펴볼 수 있다. 유니티의 버그 리포트에 이 파일 포함하는 것을 잊어서는 안된다.

성능 분석(Performance Analysis)

성능 문제를 만나면 유니티 프로필러를 붙여서 어떤 상황인지 볼 수 있다.

이를 위해서 아래 File -> Build 세팅을 통해 "Development Build" 체크박스를 체크하고 빌드 해야 한다. 이렇게 해야 유니티가 디바이스에 연결 할 수 있다.

  • 디바이스에서배포하고앱을실행
  • 디바이스와개발컴퓨터를같은네트워크에두어기기들이서로찾을있게.
  • 유니티에있는 Open Profiler 창을사용하고, Active Profiler 메뉴에서 WP8Player 선택

앱을 수행하면 이제, 실시간으로 수집된 프로필 데이터를 볼 수 있다.

노트: GPU 프로필러는 윈도우폰8 플랫폼에서는 아직 지원되지 않음.

피드백 & 리비전 히스토리(Feedback & Revision history)

이 외에도 다룰 내용이 많다. 다른 시리즈 내용들 및 참고 자료도 확인하라. 놓친 부분과 더 알고 싶은 것이 있다면 jaimer@microsoft.com 에게 연락을 부탁한다.

 

Revision  

Date  

Changes  

Contributors  

1.0  

11/15/2013  

Seeding this conversation with a big brain dump. Sharing for comments.

Jaime Rodriguez (Microsoft), Keith Patton (Marker Metro), the Marker Metro team.  

1.1  

11/21/2013  

Updated with socket based networking apis addition for Windows Phone  

Jaime Rodriguez (Microsoft), Keith Patton (Marker Metro), the Marker Metro team.

1.2  

12/08/2013  

Updated github source links and renamed direct dependency to dependency injection which is more accurate  

Jaime Rodriguez (Microsoft), Keith Patton (Marker Metro), the Marker Metro team.  

1.3  

12/20/2013  

Added link to memory profiling on Unity forum. Formatting & TOC update

JC Cimetiere (Microsoft  

 


Skip to main content