Target API level升级到31后Android 12启动黑屏卡死

Target API level升级到31后Android 12启动黑屏卡死

1)Target API level升级到31后Android 12启动黑屏卡死
​2)Unity Renderer中SortingLayer、SortingOrder底层如何实现渲染排序
3)如何用Addressable实现按需下载
4)多个Package需要不同版本的DLL的解决方案


这是第309篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题,建议阅读时间10分钟,认真读完必有收获。

UWA 问答社区:answer.uwa4d.com
UWA QQ群2:793972859(原群已满员)

Android

Q:当前海外版本有硬性要求:Target API level必须升级到31,升级之后在Android 12机型上启动游戏,Unity闪屏之后卡死,其他Android版本正常。

我们使用的Unity版本:2017.4.27f
其他一些简单测试:去掉闪屏, 导出新的空工程,都会出现启动卡死。

其他一些Unity论坛上的方式尝试均失败:
https://forum.unity.com/threads/unity-2017-and-android-12.1271753/
https://forum.unity.com/threads/android-targeting-api-level-31-makes-the-game-freeze-on-android-12.1237576/

之前我们也遇到升级之后无法安装的问题,然后参照其他解决了安装,只是黑屏无法解决。当前最新尝试Unity 2019版本是正常,初步判断是与以下问题同时修复的:
https://issuetracker.unity3d.com/issues/install-parse-failed-manifest-malformed-errors-are-thrown-when-trying-to-run-an-android-application-with-target-api-level-31

不知道是否有其他大神遇到此问题并解决了?如果有升级之后正常,请告知一下Unity版本号,谢谢。

A:查了一下这个问题,是因为TelephonyManager的listen函数在Android 12过期了,如果没有授权READ_PHONE_STATE权限,此函数会抛出一个SecurityException。

而Unity在启用了自带的音频系统的情况下,恰巧在启动时机会去调用这个方法以实现“在用户接电话时游戏静音”的功能,抛出的异常影响了后续的流程导致卡死。

论坛上有人遇到了类似的问题,但是表现为崩溃:
https://forum.unity.com/threads/android-12-telephony-crash.1287986/

项目能升级引擎的话,可以试试这里提到的修复的版本:
https://issuetracker.unity3d.com/issues/android-player-crashing-in-fmod-when-targetting-sdk-level-31

如果项目不能升级引擎,也有一个解决办法:

  • 反编译classes.jar
  • 修改UnityPlayer类的addPhoneCallListener实现,判断if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) return;据说Android 12开始不需要自己处理静音了
  • 再编回classes.jar

感谢littlesome@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/63049f1a6d82e96d844891ec


Rendering

Q:Unity Renderer中SortingLayer、SortingOrder底层是如何实现渲染排序的?

A1:第一级是材质RenderQueue的区间:不透明(<2499)优先,然后半透明(>=2500)。
第二级是SortingLayer。
第三级是SortingOrder。
第四级是材质RenderQueue本身。

感谢欧月松@UWA问答社区提供了回答

A2:Unity完整渲染顺序如下:

  1. CameraDepth从小到大
    开始渲染不透明物体(RenderQueue < 2500)
  2. SortingLayer从小到大
  3. SortingOrder从小到大
  4. RenderQueue从小到大
  5. 物体深度近到深度远
    开始渲染半透明物体(RenderQueue >= 2500)
  6. SortingLayer从小到大
  7. SortingOrder从小到大
  8. RenderQueue从小到大
  9. 物体深度远到深度近

感谢萧小俊@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/631950e68d3e026b0d2bc20e


Addressable

Q:如何用Addressable实现按需下载,大体是想要实现下面两个功能:

1. 一部分资源是在游戏启动的时候去更新的。
2. 还有一部分资源是在玩家玩到某个关卡的时候,让玩家手动触发下载。当然,这些关卡,没有下载完成之前,玩家是不能玩的。

A:可参考Unity官方实例Git,其中Advanced/Play Asset Delivery这个案例很好地展示了AssetBundle和Google新格式aab的结合以及打包Asset Packs后,哪些资源预下载,哪些资源实时下载。
https://github.com/Unity-Technologies/Addressables-Sample

感谢郑骁@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/63155ee152100855895179a8


Scripting

Q:具体情况就是Google ProtoBuf库的高版本会强制依赖 System.Runtime.CompilerServices.Unsafe.dll 4.0.4.1版本。

然后Unity内置的Package com.unity.collections会自己带进来一个DLL,并且版本不匹配。

现在有没有办法,导入一个DLL,并且只让某一个Package内的代码进行引用。或者有没有其他替代方案,比如禁止com.unity.collections带入自己的Unsafe.dll之类的流程?

其他就是考虑一个流程重新编译ProtoBuf的动态库,使其内含一个自己用的依赖库。但是这个依赖库也不好找源码。

主要问题是:com.unity.collections是Unity原生并自动植入的,不进入Packages路径,直接植入到Library。所以没有办法手动调整路径。现在暂时是用脚本在启动编辑器时替换Library里面的动态库。但是这个流程不干净,希望有个干净的做工。

A:先把项目中重复度高的DLL都放在一个Common Package中,然后把com.unity.collections拉到本地变成Local Package,再去依赖Common Package,最后就让Google ProtoBuf也去依赖这个Common Package。

对于Unity原生并自动植入的Package,一般从Library拉到本地就行,注意一下最后的package-lock.json文件中com.unity.collections的Version为file:XXXXX,并且Source显示为Embedded就代表成功了。

感谢萧小俊@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/631873958d3e026b0d2b0c02

封面图来源于网络


今天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题也许都只是冰山一角,我们早已在UWA问答网站上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入,也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。

官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
UWA学堂:edu.uwa4d.com
官方技术QQ群:793972859(原群已满员)