问题 在使用Unity 2017.4.16开发时经常遇到关闭游戏预览的时候Unity Crash的情况,经过查询log文件可以找到出问题的原因。要注意的是,每一次运行Unity的时候会重新创建这个文件,所以崩溃之后要立即去查看或者把日志保存下来。
分析 Unity Editor的崩溃日志存放在C:\Users\YOURNAME\AppData\Local\Unity\Editor\Editor.log
,崩溃之后可以查看这个日志,我这里崩溃部分的日志是这样的(而且每次崩溃都一样):
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 31 32 33 ========== OUTPUTING STACK TRACE ================== 0x00007FFD006892BB (AkSoundEngine) AK::MemoryMgr::Term 0x00007FFD006881FE (AkSoundEngine) AK::MemoryMgr::Free 0x00007FFD005A8F98 (AkSoundEngine) AK::SoundEngine::Term ERROR: SymGetSymFromAddr64, GetLastError: '试图访问无效的地址。 ' (Address: 00007FFD00595277) 0x00007FFD00595277 (AkSoundEngine) (function-name not available) 0x000000005F51B0BD (Mono JIT Code) (wrapper managed-to-native) AkSoundEnginePINVOKE:CSharp_Term () 0x000000005F51AF9A (Mono JIT Code) [C:\WorkSpace\Client\Assets\Wwise\Deployment\API\Generated\Windows\AkSoundEngine_Windows.cs:2331] AkSoundEngine:Term () 0x000000005F5190A8 (Mono JIT Code) [C:\WorkSpace\Client\Assets\Wwise\Deployment\Components\AkTerminator.cs:107] AkTerminator:Terminate () 0x000000005F518925 (Mono JIT Code) [C:\WorkSpace\Client\Assets\Wwise\Deployment\Components\AkTerminator.cs:57] AkTerminator:OnApplicationQuit () 0x0000000000D87472 (Mono JIT Code) (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr) 0x00007FFCD7A864D3 (mono) [c:\buildslave\mono\build\mono\mini\mini.c:4937] mono_jit_runtime_invoke 0x00007FFCD79D8A2D (mono) [c:\buildslave\mono\build\mono\metadata\object.c:2623] mono_runtime_invoke 0x0000000140A34E2C (Unity) scripting_method_invoke 0x0000000140A287FA (Unity) ScriptingInvocation::Invoke 0x00000001409F3D28 (Unity) MonoBehaviour::HandleNotifications 0x00000001403BF961 (Unity) MessageHandler::HandleMessage 0x00000001403C7634 (Unity) GameObject::SendMessageAny 0x00000001407186D2 (Unity) SendMessageToEveryone 0x0000000140720DBF (Unity) NotifyPlayerQuit 0x00000001411F0FE5 (Unity) PlayerLoopController::ExitPlayMode 0x00000001411F17AD (Unity) PlayerLoopController::SetIsPlaying 0x00000001411F25F6 (Unity) Application::TickTimer 0x00000001414198DF (Unity) MainMessageLoop 0x000000014141B19C (Unity) WinMain 0x0000000141E74068 (Unity) __tmainCRTStartup 0x00007FFD21B47974 (KERNEL32) BaseThreadInitThunk 0x00007FFD2401A271 (ntdll) RtlUserThreadStart ========== END OF STACKTRACE ===========
通过分析和查询资料可以看出崩溃和AkSoundEngine有关系,Wwise是Audiokinetic开发的游戏互动音频引擎,支持Unity和Unreal等游戏引擎,AkSoundEngine就是Wwise中的东西。
在Unity中,运行游戏的时候会创建AkInitializer,退出游戏的时候会销毁。AkInitializer使用的是Lazy模式的初始化,通过设置断点发现编辑器的游戏预览退出的的时候,偶尔会在MonoBehaviour的OnDisable()方法中重新创建的音频管理器对象,也就是说有了两个,但是这种方式又是Audiokinetic允许的。因此,退出游戏的时候可能销毁的不是一开始创建的那个音频管理器对象,就会崩溃。
解决方法 也就是说,我们要保证销毁器销毁的是创建的那个对象,所以要修改AKTerminator.cs这个文件,在里面加上一个判断:
1 2 3 4 5 6 7 8 9 void OnEnable (){ if (ms_Instance == null && AkSoundEngine.IsInitialized()) { ms_Instance = this ; } }
加上OnEnable
这个函数之后果然没有再崩溃了。
注意事项 使用这个解决方法可以解决大部分情况下的崩溃,但是如果在游戏运行时修改代码,然后再关闭游戏依然会导致崩溃,似乎是必现。
参考链接:unity crash when exit the application in play-in-editor using AkTerminator.cs