Android刘海适配

Android刘海适配

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

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


本期目录:

  • Android刘海适配
  • AssetBundle名称的设置
  • Shader优化Tips疑问
  • HDRP Shader中如何获取深度值

UI

Q:大家都是怎样进行Android刘海屏适配的呢?对于各个机型是否开启了刘海都是怎样进行判断的?刚了解到一个方案就是:

1.获取机型,对小米、华为、oppo、vivo这个几款机型进行判断。
2.在判断是否是28版本的SDK,如果是就进行调用机型适配;如果不是,当小于28不做适配;当大于28使用Android原生的进行适配。
3.进行各个厂商刘海手机适配时,判断用户是否都打开了刘海屏(这个是重点)。
4.获取刘海高度进行适配。

主要是在第三步,获取用户是否打开刘海的时候,这个接口一般是通过反射调用Android各个手机厂商的底层代码,关键在于这个厂商是否开放了这个接口,所以获取用户手机是否开启刘海就是关键了,怎样去获取,是值得讨论的一个点。

A:9.0以前的系统判断是否开启,我们是提取各个厂家ROM里的Framework,反编译出来,找到相关接口,然后反射调用。

Github上有已经提取好的,提取方法在这里:https://github.com/dstmath/HWFramework

比如oppo的,应该就是这个接口了:
https://github.com/dstmath/OppoFramework/blob/96194a5ca570415a4cdebdaa57562a75d34fed94/A5_8_1_0/src/main/java/com/color/util/ColorDisplayCompatUtils.java#L890

如果反射失败了要Fallback到安全的适配方案上去。其实厂商修改这些接口的可能性不是非常大,他们自家的App也都在使用这些接口。

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


资源管理

Q:关于设置AssetBundle(以下简称AB)名的问题。如果我有个A预制体用到10个资源,那我分别把他们都设置相同的AB名,即同一个AB包里面,我只给A设置AB名,其他都不设,这样打成的AB包也都会包括其他的资源,然后同时加载A预制体。是哪种方案的效率高呢?

A1:姑且把这两种方案称为"手动处理依赖"和"Unity自动处理依赖",仅看加载这AB,效率是一样的,因为两种方式打包出来的AB内容一样,但是“Unity自动处理依赖”的方案中,被依赖的资源是隐式地被打入AB中,如果别的AB中的资源也引用了这些隐式资源,那么这些隐式资源又会被打入别的AB中,就会造成资源的冗余,进而造成AB文件变大、安装包变大、加载变慢、内存升高等问题。Shader的冗余更会造成Shader.Parse重复执行导致WarmUp时间过长或运行时卡顿。

因此推荐"手动处理依赖"这种方案,这种方案中,显式地指定资源被打入AB中,别的AB中的资源如果也依赖了这些显式资源,Unity会生成AB之间的依赖关系,加载AB中资源之前,确保打开该AB依赖的其他AB即可(也就是将被依赖的AB加载到内存中),Unity会自动去被依赖的AB中寻找并加载被依赖的资源。

另外,设置AB Name这种做法效率比较低,与Unity Meta文件耦合严重,可以在打包时自动分析资源依赖的文件,更多细节可以参见这个轻量级的打包方案:XAsset,推荐初步接触AB打包和加载的同学阅读其源码。
感谢张迪@UWA问答社区提供了回答

A2:楼上说的很清楚了,如果只是加载使用这个预设的话,这些资源怎么处理都没问题。不过实际开发中是不可能这么简单的。

设置AB Name的应该和LZ4压缩联动一起用,无论是所有资源打一个AB包还是每一个资源都打成单独AB包,我觉得都是不好的。应该按需规划资源的使用情况,比如一些基础的依赖严重的动画,Mesh、粒子特效贴图等可以打成一个基础资源包。对于UI,Prefab和图集可以打在一起(UGUI比较特殊,也推荐这么做),音乐文件也可以打在一起,一些Prefab特有的资源,设定单独的AB Name单独打包。

加载相关的,因为是LZ4压缩方式,加载出AB的时候,只是加载了头文件之类的数据,所以不需要加载完毕就Unload,这样不仅浪费CPU也会造成内存冗余(特别是你设置了多个AB Name)。自己做好记录,加载了那些AB,和解压了哪些A,到时候需要释放的时候心里有数,也不会造成内存泄露。
感谢robot@UWA问答社区提供了回答

该问答来自UWA问答社区,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5c49b0be7692f15c777a54e2


Shader

Q:在Unity官网上看到这样一段游戏描述里用了不少Color Mask表示很方,请大神解惑。

请输入图片描述

A:可以从两点来看:

1.实际影响有多大?
原则上Profiling说话,但有时候挺麻烦。比如:直接影响的数据不好细分拆出来、 测试结果依赖于具体硬件等等。那就靠理论推演。

2.背后的根本原因是什么?
Tip背景是移动平台GPU,很容易想到TB(D)R,也很容易想到和Alpha Test类似,假设不透明物体A遮挡了B,A没有Color Mask的情况下,HSR(Early-z)阶段,B被遮挡的部分就可以全抛了,不需要走后面的PS(FS);而如果A有Color Mask,B就不能抛,因为此时Color Mask不确定(PS中才能确定),B被遮挡的部分可能会对最终Color有贡献。那么,Color Mask = 更多的Overdraw。

Color Mask的好处呢,Color的部分分量不需要读写FrameBuffer - 因为IMR下读写FrameBuffer是直接和内(显)存交互,速度很慢,带宽消耗大,减少这块的开销有意义;而TB(D)R下,着色过程中读写FrameBuffer的操作都是在片上高速缓存中进行,很快,减少这块很可能抵不过增加的Overdraw开销。

实践上,如果图简单省事,能不用就不用。

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


HDRP

Q:在HDRP中使用 SAMPLE_DEPTH_TEXTURE 宏获取到的深度值是错误的,HDRP中深度图的存储方式改变了,有点类似一个Mip的图集,ShaderVariables.hlsl 中的 SampleCameraDepth 方法,但是引用了必备的.hlsl文件后仍然提示 undeclared identifier 'SampleCameraDepth’,如果有在HDRP中使用过这个方法或者在HDRP中正确获取过深度值的同学,请不吝赐教,先表示感谢了。

A:解决了,四个方式可以获取到深度值。

1.float depth = LOAD_TEXTURE2D(_CameraDepthTexture, screenPos);
2.float depth = LOAD_TEXTURE2D_LOD(_CameraDepthTexture, screenPos, 0).r
3.float depth = LOAD_TEXTURE2D_LOD(_DepthPyramidTexture, screenPos, 0).r
4.float depth = LOAD_TEXTURE2D(_DepthPyramidTexture, screenPos).r

感谢上午八点@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5c458cbffa09561eb1aa7884


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

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

封面图来源:VaOceanMobile
https://lab.uwa4d.com/lab/5b862a8c02004fb65977f8ac