문서의 이전 판입니다!


목차

문제 해결

이 섹션은 유니티를 사용하면서 생기는 문제들을 언급합니다. 문제를 겪고 있는 플랫폼을 선택해 주세요. DesktopTroubleShooting

Desktop!

desktop«

MonoDevelop에서 디버그 버튼이 비활성화 되어 있어요!

  • 이것은 MonoDevelop가 유니티 실행 파일을 찾을 수 없을 때 입니다. MonoDevelop의 환결 설정에서 Unity/Debugger섹션으로 가서 어디에 유니티 실행 파일이 있는지 입력하세요.

Mono Develop에서 웰컴 페이지를 없앨 방법은 없나요?

  • 네, 있습니다. MonoDevelop 환경 설정에서 Visual Style 섹션에 가서 "Load welcome page on startup"의 체크를 해제 하세요.

Geforce 7300GT on OSX 10.6.4

  • 지연 렌더링이 비활성화 되어있는데 왜냐하면 재료가Geforce 7300GT on OX 10.6.4에서 보여지지 않기 때문입니다. 이것은 버그가 있는 비디오 드라이버 때문입니다.

Windows x64에서 스크립트가NullReferenceException를 발생키기면 크래쉬 됩니다

그래픽

프레임속도 와/또는 시각적 인공물 늦추기.

  • 이것은 비디오 카드의 드라이버가 최신 것이 아니면 생길 수 있습니다. 그래픽 카드 제공자에 의한 최신 공식 드라이버를 설치하세요.

그림자

그림자가 보이질 않아요!

  • 그림자는 유니티 프로에서만 지원이 됩니다. 물론 Projector같은 간단한 그림자 함수는 가능합니다.
  • 그림자는 특정 그래픽 하드웨어 지원을 필요로 합니다. 좀더 많은 정보는 유니티 그림자를 보세요.
  • 그림자가 완전히 비활성화 되지 않으면 Quality Settings를 보세요.
  • _그림자는 현재 안드로이드와 iOS에는 지원되지 않습니다._

어떤 객체는 그림자를 내지도 받지도 않습니다

첫째, Renderer는 자신의 그림자에 그림자 받는 것에는 Receive Shadows를 그림자를 내는 것에는 Cast Shadows를 가져야 합니다(둘다 기본 입니다).

다음으로 불투명한 객체만이 그림자를 내고 받을수 있습니다. 즉 내장된 Transparent나 Particle 쉐이더를 사용하면 그림자를 볼 수 없을 것입니다. 대부분의 경우 Transparent Cutout쉐이더에 가능합니다(펜스나 생물 객체, 등등). 만약 사용자 정의 Shaders를 사용한다면 그 쉐이더는 pixel-lit이고 Geometry render queue를 사용하여야 합니다. VertexLit쉐이더를 사용하는 객체는 그림자를 받지 않습니다(그러나 낼수는 있습니다).

마지막으로 픽셀 빛 많이 그림자를 냅니다. 만약 어떤 빛이 씬에 몇 개의 빛이 있건 항상 그림자를 내기를 원한다면 Force Pixel렌더 모드를 설정하세요(Light를 보세요).

iPhoneTroubleShooting

iOS!

ios«

iOS 장치에서의 문제 해결

유니티 iOS에디터에서는 문제가 없다가 실제 장치에서는 작동하지 않는 알려진 케이스들이 있습니다. 그 문제는 주로 코드나 컨텐츠 퀄리티와 관련되어 있습니다. 이 챕터에서는 가장 흔한 경우를 설명합니다.

Xcode 3.2.x fails to build application with error "libiPhone-lib.a, missing required architecture i386 in file Undefined symbols: "Register_UnityEngine_Input_GetMouseButtonDown()", referenced from: RegisterAllStrippedInternalCalls() in RegisterMonoModules.o

이 빌드 에러는 보통Player Settings에서 non-simulator SDK가 선택되면 발생하는데 나중에 Xcode 에서는 SDK가 시뮬레이터로 바뀝니다. 시뮬레이터 빌드를 실행하기 위해서는 Player Settings에서simulator SDK를 선택해야 합니다.

Xcode 4.x fails to build application with error "No architectures to compile for (ARCHS=armv6, VALID_ARCHS=i386)."

현재 유니티는 Xcode 4.x에 대한 제한된 지원을 하고 있고 최종 프로그램을 빌드하려면 약간의 수동 작업의 노력이 필요합니다. 빌드하고 실행하면 유니티 iOS가 생성한 Xcode 프로젝트를 엽니다 하지만 이것은 적절한 빌드 타겟와 적절한 목표 장치를 선택하지 못합니다. 장치에서 테스트를 위해 빌드한다면 "Unity-iPhone"과 맥에 연결된 iOS장치를 빌드 타겟으로 선택합니다. 시뮬레이터에서 테스트를 위해 빌드한다면(_주의:_ Player Settings에서 적절한 SDK가 필요합니다) "Unity-iPhone-simulator"와 적절한 시뮬레이터 장치를 선택해야합니다.

얼마의 시간이 지나면 게임이 멈춥니다. Xcode가 상태바에 "interrupted"를 보여줍니다.

이에는 몇 가지 이유가 있을 수 있습니다. 보통 아래와 같습니다:

  1. 스크립트 에러. 초기화된 변수 사용하기 등.
  2. 타사의 컴파일된 라이브러리 사용하기. 그런 라이브러리는 iOS SDK 링커에서 문제를 일으키고 랜덤 크래시를 만듭니다.
  3. Serializable 스크립트 속성에 파라미터로generic type을 value types과 사용할 때(like List<int>, List<SomeStruct>, List<SomeEnum>).
  4. 코드 스트리핑이 활성화 되어있을 때 반사 사용하기.
  5. native plugin interface 에서의 에러(managed code method signature가native code function signature와 맞지 않음).

자세한 사항은 XCode 디버거 콘솔을 검토해 봐야 합니다. Xcode디버거 콘솔은 Xcode 메뉴의Run→Console에서 접근 가능합니다.

Xcode 콘솔은 "Program received signal: &#8220;SIGBUS&#8221; 또는 EXC_BAD_ACCESS 에러를 보여줍니다.

이 메세지는 사용자 프로그램이 Null Reference Exception을 받으면 보통 iOS장치에서 나타납니다. 무엇이 잘못 되었는지 알아내는 두 가지 방법이 있습니다:

Managed stack traces

유니티 버전 3.4이후로Null Reference Exception를 핸들하는 프로그램이 포함되어 있습니다. AOT컴파일러는 객체 함수나 필트가 접근될 때마다 널 참조를 작은 체크를 가지고 있습니다. 이 기능은 사용자 스크립트 성능에 영향을 주고 이것이 오직 개발 빌드에서만 활성화된 이유입니다(기본 라이센스 사용자는 Build Settings 대화창에서 "development build"를 활성화 한것으로 충분합니다. 프로 라이센스 사용자는 추가로 "script debugging" 옵션을 체크해야 합니다). 모든 것이 제대로 설정이 되었고 .NET 코드에서 에러가 발생하면 더 이상 EXC_BAD_ACCESS를 하지 않습니다. 대신 .NET 익셉션 텍스트가 Xcode콘솔에 보여집니다(또는 사용자 캐치문에 잡힙니다). 보통 결과물은:

Unhandled Exception: System.NullReferenceException: A null value was found where an object instance was required.
  at DayController+$handleTimeOfDay$121+$.MoveNext () [0x0035a] in DayController.js:122 

위에서는 DayController 클래스의 coroutine처럼 작동하는handleTimeOfDay 함수에 문제가 있습니다. 또한 이 샘플 "DayController.js:122"처럼 스크립트 코드이면 정확한 코드라인을 볼 수 있을 것입니다. 다음 코드에 해당합니다:

 Instantiate(_imgwww.assetBundle.mainAsset);

보통 이것은 스크립트 코드가 WWW클래스가 성공적으로 에셋 번들을 다운로드 했는지 적절히 체크를 하지 않고 그 필드에 접근하면 발생합니다.

Native stack traces

Native stack traces 는 에러 조사에 좀더 강력한 툴입니다. 또한 보통 이 에러가(하드웨어 메모리 액세스) 발생하면 더 이상 진행이 되지 않습니다. native stack trace를 얻기 위해서 타입 스레드가 Xcode디버거 콘솔을 제외한 모든 곳에 적용됩니다. 스택 트레이스를 주의 깊게 조사하세요. 아마 어디에서 에러가 일어났는지 힌트를 줄 것입니다. 아마 아래와 같은 것을 볼 것입니다:

...
Thread 1 (thread 11523): 
#0 0x006267d0 in OptionsMenu_Start () 
#1 0x002e4160 in wrapper_runtime_invoke_object_runtime_invoke_void_this__object_intptr_intptr_intptr () 
#2 0x00a1dd64 in mono_jit_runtime_invoke (method=0x18b63bc, obj=0x5d10cb0, params=0x0, exc=0x2fffdd34) at /Users/mantasp/work/unity/unity-mono/External/Mono/mono/mono/mini/mini.c:4487
#3 0x0088481c in MonoBehaviour::InvokeMethodOrCoroutineChecked ()
...

무엇보다 _"Thread 1"_를 위한 스택 트레이스를 찾아야 합니다. 이것은 메인 스레드 입니다. 스택 트레이스의 첫 라인은 에러가 일어나는 곳을 가르쳐줍니다. 이 예제는NullReferenceException이 "OptionsMenu" 스크립트의 "Start"함수 안에서 발생했음을 알려줍니다. 이 함수의 구현을 주의 깊게 보는것은 문제의 원인을 파악하는데 도움이 될 것입니다. 보통 NullReferenceExceptions은 Start 함수에서 초기화 순서에 대한 잘못된 가정이 만들어질 때 발생합니다. 어떤 경우에는 디버거 콘솔에 부분적인 스택 트레이스가 보여집니다:

Thread 1 (thread 11523): 
#0 0x0062564c in start ()

이것은 사용자 프로그램을 위한 릴리즈 빌드 중에native symbol이 삭제된 것을 알려줍니다. 완전한 스택 트레이스는 아래의 지시를 따라 얻을 수 있습니다:

  • Xcode프로젝트에서 디버그 설정을 선택합니다.
  • 모든 타겟을 클리어 합니다.
  • 빌드하고 실행합니다.
  • 위 설명처럼 스택 트레이스를 얻습니다.

EXC_BAD_ACCESS가 외부 라이브러리가 유니티 iOS 프로그램에 링크될 때만 발생합니다.

이것은 보통 외부 라이브러리가 ARM Thumb instruction set과 함께 컴파일될 때 발생합니다. 현재 그런 라이브러리는 유니티 iOS와 호환되지 않습니다. 이 문제는 라이브러리를 Thumb instruction없이 다시 컴파일해서 쉽게 해결할 수 있습니다. 라이브러리의 Xcode프로젝트를 위한 자세한 지시:

  • Xcode 메뉴에서 "Project""Edit active target"
  • "Target Info"대화 창에서 "Configuration: All Configurations"선택
  • 탐색 필드에 "thumb" 입력
  • "Compile for Thumb" 설정이 나타나면 체크를 해제하고 라이브러리 리빌드 .

만약 라이브러리 소스를 볼 수 없으면 라이브러리 제공자에게 thumb버전이 아닌 라이브러리를 요청합니다.

Xcode 콘솔이 크래쉬 직후 "WARNING -> applicationDidReceiveMemoryWarning()"를 보여줍니다.

(가금 Program received signal: �0�같은 메세지를 볼 수 있습니다.) 이 경고 메세지는 많은 경우 심각한 것은 아니고 iOS가 메모리가 적어 프로그램에 메모리를 프리할 것을 요청하는 것입니다. 보통 메일 같은 백그라운드 프로세스들이 메모리를 풀어주며 사용자 프로그램은 계속 실행될 수 있습니다. 그러나 사용자 프로그램이 계속 메모리를 사용하거나 더 원할 경우 OS는 어느 시점에서 프로그램을 종료하기 시작하고 사용자 프로그램이 종료 될 수도 있습니다. 애플은 어떤 메모리 사용이 안전한지 문서화 되지 않았지만 경험적 관찰에 의하면 25MB이하의 RAM(80MB: 3세대 장치)을 이용하는 프로그램은 메모리 사용 문제를 가지지 않습니다. 40MB의 RAM을 사용하는 프로그램은 1-2세대 장치에서 문제를 야기하고 장치를 재시작해야 할 수도 있습니다. 사용자가 의존해야 하는 주요 통계는 프로그램이 얼마나 많은 RAM을 사용하는가 입니다. 사용자 프로그램의 메모리 사용은 다음 세가지 주요 부분으로 이루어 집니다:

  • 응용 프로그램 코드 (OS는 RAM에 프로그램을 로드하고 유지할 필요가 있습니다)
  • native heap (상태, 에셋 등을 RAM에 저장하기 위해 엔지에서 사용됨)
  • managed heap (Mono 실행시에 C#과 JavaScript 객체를 유지하기 위해 사용됨)

사용자 프로그램의 메모리 사용은 Xcode Instruments 툴 (Activity MonitorObject Allocations)에서 감시될 수 있습니다. Xcode의 performance 툴인 Run→Start with Performance Tool→Activity MonitorRun→Start with Performance Tool→Object Allocations에서 실행될 수 있습니다. 첫 번째 툴은 모든 프로세스의 사용자 프로그램이 사용하는 전체 RAM양을 나타내는 실제 메모리를 포함한 통계를 보여줍니다.

_주의:_ internal profiler은 .NET스크립트에 의해 할당된 힙만을 보여줍니다. 총 메모리 사용은 위에서처럼 Xcode Instruement에서 얻을 수 있습니다. 이 숫자는 메모리에 로드 되어 7MB를 차지하는 프로그램 바이너리, 어떤 표준 프레임워크 버퍼, 유니티 엔진 내부 상태 버서, .NET 런타임 힙(internal profiler에서 보여주는 값) 그리고 그 밖의 값들을 포함합니다.

다른 툴은 사용자 프로그램에 의한 모든 할당과 native heap + managed heap 통계를 포함합니다(프로그램의 현재 상태를 알기 위해 Created and still living 박스를 확인하는 것을 잊지마세요). Net bytes 값을 보아야 합니다.

어떻게 메모리 사용을 낮게 유지하는지에 대한 힌트:

  • 가장 강력한 iOS 스트리핑 옵션(고급 라이센스 기능)을 사용해서 프로그램 바이너리 크기를 줄이고 다양한 .NET 라이브러리 불필요한 의존성을 피하세요. 자세한 사항은 player settingsplayer size optimization를 보세요.
  • 컨텐츠 크기를 줄이세요: 텍스트에는 PVRTC압축을 사용하고 낮은 다각형 모델을 사용하세요. 자세한 것은 reducing filesize을 참조하세요.
  • 스크립트에서 너무 많이 할당하지 마세요. internal profiler에서 mono heap크기와 사용을 감시하세요.
  • _주의:_ 유니티 3.0에서는 씬을 로딩하는 구현이 많이 바뀌었고 이제 모든 씬에셋은 미리 로드됩니다. 이것은 게임 객체를 인스턴스화 할때의 급격한 하락을 줄여줍니다. 게임 플레이 동안 에셋의 로딩과 언로딩에 관해 좀더 미세한 컨트롤을 원하면Resources.Load / Object.Destroy을 사용하세요.

OS에게 얼마나 메모리가 남아 있는지 물어보는 것은 사용자 프로그램이 얼마나 잘 돌아가고 있는지 알아보는 좋은 방법인듯 합니다. 하지만 이것은 실제 그렇지 않은데 왜냐하면 OS는 많은 동적 버퍼와 캐쉬를 이용하기 때문입니다. 항상 사용자 프로그램의 메모리 사용을 확인하고 이것을 주요 통계로 사용하세요. 그것만이 가장 믿을만한 방법일 것입니다. 그저 OS에게 얼마나 메모리가 남았나 물어보는 것은 별 소용이 없습니다. 툴에서 그래프가 위의 변화를 어떻게 보여주는지 주의깊게 보세요. 특히 새로운 레벨이 로딩된 후에 주의하세요.

게임이 Xcode에서는 잘 시작되었는데 수동으로 장치에서 시작될 때 첫 번째 레벨 로드에서 크래쉬합니다.

몇 가지 이유가 있을 수 있습니다. 좀더 자세한 정보를 위해 장치 로그를 볼 필요가 있습니다. 장치를 맥에 연결하고 Xcode를 싲가하고 Xcode메뉴의 Window→Organizer로 가서 Organizer의 왼쪽 툴바에서 사용자 장치를 선택하고 "Console" 탭을 클릭하고 최근 메세지를 리뷰합니다. 추가로 크래쉬 리포트를 볼 필요가 있습니다. 어떻게 크래쉬 리포트를 얻는지는: http://developer.apple.com/iphone/library/technotes/tn2008/tn2151.html.

Xcode Organizer 콘솔이 "killed by SpringBoard"를 포함합니다.

iOS프로그램에서는 첫 번째 프레임을 렌더하고 입력을 처리하는데 걸리는 시간의 제한에 대한 것은 잘 문서화 되지 않았습니다. 사용자 프로그램이 이 제한을 넘기게 되면SpringBoard에 의해 종료되게 됩니다. 전형적인 경우는 프로그램이 큰 첫 번째 씬을 가졌을 때입니다. 이 문제를 피하기 위해서는 스플래쉬 화면만 보여주고 하나나 두 개의 프레임을 기다리면서 실제 씬의 로드를 시작하는 작은 초기 씬을 만들 것을 권합니다. 이것을 위한 코드 샘플:

function Start () {
    yield;
    Application.LoadLevel("Test");
}

Type.GetProperty() / Type.GetValue()가 장치에서 크래쉬를 야기합니다

현재 Type.GetProperty()Type.GetValue().NET 2.0 Subset에서만 지원합니다. Player Settings에서 .NET API 호환 레벨을 선택합니다.

_주의:_ Type.GetProperty()Type.GetValue()는 managed code stripping 과 호환되지 않을 수 있으며 사용자 정의의 스트리핑이 되지 않는 타입 리스트를 제공함으로써 스트리핑을 사용하는 타입을 제외시켜야 할수도 있습니다. 좀더 자세한 사항은 iOS player size optimization guide을 보세요.

게임이 다음 에러와 함께 크래쉬합니다 "ExecutionEngineException: Attempting to JIT compile method 'SometType`1<SomeValueType>:.ctor ()' while running with --aot-only."

iOS의 Mono .NET 구현은 AOT(ahead of time compilation to native code) 기술에 기반을 둡니다. 이 기술은 자체의 한계를 가집니다. 이것은 다른 코드에의해 사용되는 그 generic 타입의 함수(값 타입이 generic 파라미터로 사용 되었을 때)만을 컴파일합니다. 그런 함수가 반사나 본래의 코드(즉serialization시스템)를 통해 사용이 되면 AOT컴파일 도중에 스킵됩니다. AOT컴파일러는 모의 함수를 스크립트 어딘가에 추가함으로써 코드를 추가하라는 것을 알려주고 없는 함수를 터치하여 미리 컴파일 되게 합니다.

void _unusedMethod()
{
    var tmp = new SometType<SomeValueType>();
}

_주의:_ 값 타입은 기본 타입, enums, structs 입니다.

System.Security.Cryptography과 managed code stripping의 조합이 장치에서 겪는 다양한 크래쉬

.NET 암호화 서비스는 반사에 크게 의존하므로 정적 코도 분석에 의존하는managed code stripping과 호환되지 않습니다. 가끔 가장 쉬운 방법은 스트리핑 프로세스에서 모든 System.Security.Crypography네임스페이스를 제외 시키는 것입니다.

스티리핑 프로세스는 사용자 정의된 link.xml파일을 유니티 iOS 에셋폴더에 추가함으로써 사용자 정의 할 수 있고 어떤 타입 또는 네임스페이스를 스트리핑에서 제외 시켜야 하는지 지정합니다. 좀더 자세한 사항은 iOS player size optimization guide을 보세요.

link.xml

<linker>
       <assembly fullname="mscorlib">
               <namespace fullname="System.Security.Cryptography" preserve="all"/>
       </assembly>
</linker>

"Ran out of trampolines of type 1/2" runtime error

이 에러는 보통 사용자가 많은recursive generics을 사용하면 발생 합니다. 사용자는 첫번째 두번째 타입을 더 할당하기 위해 AOT컴파일러에게 힌트를 줍니다. 추가적인 AOT컴파일러 명령어 라인 옵션은 PlayerSettings의 다른 설정 옵션에서 지정될 수 있습니다. Type 1 trampolines은 nrgctx-trampolines=ABCD를 지정합니다. 여기서 ABCD는 새로운 trampoline count (즉 4096)입니다. Type 2 trampolines은nimt-trampolines=ABCD을 지정합니다.

AndroidTroubleShooting

Android!

android«

안드로이드 개발 문제 해결

유니티가 사용자 프로그램을 장치에 설치 실패

  1. 사용자 컴퓨터가 실제로 장치를 감지하고 연결 되었는지 확인합니다. 좀 더 자세한 사항은 Publishing Builds에 있습니다.
  2. 유니티 콘솔에서 빨간 사인으로 마크 되어있는 에러를 찾으세요. 그것을 유용한 에러 메세지 일 것입니다.

사용자 프로그램이 시작 후 바로 크래쉬 합니다.

  1. NativeActivity를 지원하지 않는 장치와 사용하려 하지 마세요.
  2. 사용자가 가지고 있는 본래의 플러그인을 제거하도록 하세요.
  3. 스트리핑을 비활성화 하도록 하세요.
  4. 크래쉬 리포트를 얻기위해 adb logcat를 사용합니다.

DEX 빌스 실패

이것은 아래와 같이 자신을 나타낼 에러입니다

Building DEX Failed!
G:\Unity\JavaPluginSample\Temp/StagingArea> java -Xmx1024M 
-Djava.ext.dirs="G:/AndroidSDK/android-sdk_r09-windows\platform-tools/lib/" 
-jar "G:/AndroidSDK/android-sdk_r09-windows\platform-tools/lib/dx.jar" 
--dex --verbose --output=bin/classes.dex bin/classes.jar plugins
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

이것은 주로 컴퓨터에 잘못된 버전의 Java가 설치 되었을 때 입니다. 자바를 최신 버전으로 설치하고 이것은 이 문제를 해결할 것입니다.

슬립 버튼을 누르면 게임이 종료됩니다

here에 설명된 <android:configChanges> 태그를 포함하기 위해 AndroidManifest.xml 에 있는 <activity> 태그를 바꾸세요.

예제 활동 태그는 다음과 같습니다:

<activity android:name=".AdMobTestActivity"
                  android:label="@string/app_name"
                  android:configChanges="keyboardHidden|orientation">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

역링크