一、问题描述
自从Unity3D升级到2021.3.26f1这个版本之后,在崩溃监控后台就看到iOS端有一条新增的崩溃BufferMetal::EndWrite,具体崩溃对战如下:
Crashed: UnityGfxDeviceWorker
0 UnityFramework 0x10c5748 BufferMetal::EndWrite(BufferMetal::MetalVersionedBuffer*, unsigned long, bool) + 54 (MetalScratchBuffer.h:54)
1 UnityFramework 0x10d2630 GfxDeviceMetalBase::EndBufferWrite(GfxBuffer*, unsigned long) + 3349 (GfxDeviceMetal.mm:3349)
2 UnityFramework 0xf5d8dc GeometryJobTasks::PutGeometryJobTask(GfxDevice&, GeometryJobTasks::GeometryJobTask*) + 176 (GeometryJob.cpp:176)
3 UnityFramework 0xf5d7b8 GeometryJobTasks::EndFrame(GfxDevice&) + 65 (mpsc_node_stack.h:65)
4 UnityFramework 0x104a0cc GfxDeviceWorker::RunCommand(ThreadedStreamBuffer&) + 1470 (GfxDeviceWorker.cpp:1470)
5 UnityFramework 0x10d82dc GfxDeviceWorkerAutoreleasePoolProxy + 5750 (GfxDeviceMetal.mm:5750)
6 UnityFramework 0x104b868 GfxDeviceWorker::RunExt(ThreadedStreamBuffer&) + 381 (GfxDeviceWorker.cpp:381)
7 UnityFramework 0x10433ac GfxDeviceWorker::RunGfxDeviceWorker(void*) + 339 (GfxDeviceWorker.cpp:339)
8 UnityFramework 0xba2550 Thread::RunThreadWrapper(void*) + 82 (Thread.cpp:82)
9 libsystem_pthread.dylib 0x19ac _pthread_start + 148
10 libsystem_pthread.dylib 0xe68 thread_start + 8
表现上是低内存,像是内存占用满了导致的崩溃。但是从理性分析,这个版本的内容,内存中占用理论上不应该与之前版本有重大变化。而且正好是升级了Unity的时候,所以最大的可能性是触发了什么Unity版本bug,导致访问了无效内存导致。
于是就开始搜集跟这个崩溃有关的资料。
在Unity官方论坛上,发现了如下的帖子:
大致问题原因是,粒子系统出了问题导致的崩溃。
二、修复版本
于是,便开始大量翻阅Unity的版本更新日志,查找符合描述的崩溃修复,看能不能通过后续的版本升级来修复这个崩溃。
在Unity3D 2021.3.28f1版本的更新日志中,发现了如下的修复:
Unity3D 2021.3.28f1 Release Note
那么根本上的解决方案就是升级到比这个版本更新的Unity版本。
三、临时方案
升级Unity3d对于在线上稳定运营的项目来说还是需要谨慎的,需要更多时间测试。
通过帖子和Release Note描述可知,其实是因为Unity3D的多线程渲染功能(multi-thread rendering)的bug导致的。所以有一个临时方案是,在Unity升级测试完毕之前,可以先发一个把多线程渲染关闭的版本争取点时间,然后后续升级完再打开。多线程渲染对性能有影响,经过线上历史数据测得,在现有玩家群体,这个功能对Android平台的性能更大,而iOS影响小一些。而这次崩溃影响的又是iOS平台,于是临时只关闭了iOS平台的多线程渲染,然后升级Unity,等测试完毕Unity升级的版本再打开多线程渲染即可。