1)Lua全局变量代码规范
2)AssetBundle LockPersistentManager开销
3)Unity内置字体在资源检测报告中不算冗余资源
4)特定Android设备上,Adreno发生冻屏问题
5)Mask和RectMask性能上的区别html
这是第238篇UWA技术知识分享的推送。今天咱们继续为你们精选了若干和开发、优化相关的问题,建议阅读时间10分钟,认真读完必有收获。git
UWA 问答社区:answer.uwa4d.com
UWA QQ群2:793972859(原群已满员)github
Q:使用Lua语言做为脚本辅助开发已经很是流行了,可是Lua语言中的全局变量是一个使人头疼的问题,由于无需声明就可使用、编译器编译不会针对重命名和覆盖进行报错,稍不留神就会覆盖掉全局变量致使Bug,并且全局变量引用GameObject有可能会形成泄露。异步
你们在开发过程当中,对于Lua全局变量会制定什么代码规范吗?例如:何时可使用全局变量?如何声明?如何规避覆盖等问题,谢谢。函数
A:能够在Lua虚拟机启动之后,在适当的时机执行一下luaGlobalCheck.lua文件,这个文件里面会设置一下_G的元表和元方法,经过重写_newindex和 _index元方法的方式来作到禁止新建全局变量和访问不存在的全局变量时提示错误。这样能够作到避免随意新建全局变量污染环境和覆盖的问题。性能
luaGlobalCheck.lua代码以下:测试
setmetatable(_G, { -- 控制新建全局变量 __newindex = function(_, k) error("attempt to add a new value to global,key: " .. k, 2) end, -- 控制访问全局变量 __index = function(_, k) error("attempt to index a global value,key: "..k,2) end })
感谢马三小伙儿@UWA问答社区提供了回答字体
Q:观察性能曲线,发现某一帧AssetBundle加载中,LockPersistentManager耗时比较大。请问这块是否可以优化?优化
A1:这说明当前帧或前几帧中存在较大量的资源在经过LoadAsync来进行加载,其本质是所加载的资源过大所致,对自身资源进行合理优化可下降Loading.LockPersistentManager的开销。另外,将异步加载换成同步加载,LockPersistentManager就不会出现了,但其总加载耗时是没有变化的,由于总加载量没变。关于主要资源的加载优化,可参考以下连接:
《Unity加载模块深度解析(纹理篇)》
《Unity加载模块深度解析(网格篇)》
《Unity加载模块深度解析(Shader篇)》
《Unity加载模块深度解析之动画片断》
《移动游戏加载性能和内存管理全解析》动画
该回答由UWA提供
A2:Unity 2019.4.1版本下,实际上是bundle.LoadFromFileAsync在主线程的Integrate Asset中执行,和PreloadManager线程的LoadAssetAsync不能同时进行,必需要锁,也就出现LockPersistentmanager,一直锁到一方结束。本质仍是这块实现不完善,能够用Spin Lock一直锁到Application.backgroundLoadingPriority规定的时间再到下一帧就好了,不用一直锁到一方释放。
Unity 2019.4.11和2019.4.16修改了主线程读Bundle和等锁的问题:
我在Unity 2020.1.17版本出的iOS上测试是基本解决了:
可是还有个别异步加载主线程等锁的现象,估计是资源太大收集依赖时间太长触发的:
感谢燃野@UWA问答社区提供了回答
Q:咱们的项目工程中返现两个界面的Prefab,都是用Unity本身的Arial字体生成的Bundle,上传到资源检测,可是在报告中并未看到内置的字体是冗余资源。
A1:这个Arial是属于Unity内置资源,打包APK的时候是会被打进unity default resources里面的,因此AssetBundle中使用到了这个Arial字体都是引用关系,并不会打包进对应的AssetBundle中,所以看不到冗余是正常的。使用AssetStudio打开APK包中的assets/bin/Data/目录下的unity default resources就能够看到了,以下图:
感谢Xuan@UWA问答社区提供了回答
A2:不建议使用Arial字体,在某些低端机上中文没法显示,主要仍是默认字体在不一样机型上的不同。
感谢郑骁@UWA问答社区提供了回答
Q:特定Android设备上,Adreno发生冻屏(GPU挂起)的问题。
现象是屏幕冻住不刷新了,可是音乐和点击UI的音效还能够播放。用Unity Profiler看CPU也没异常和闪退。冻屏时抓到的错误日志可戳原问答查看,麻烦你们帮看下有什么启发,谢谢!
A1:不肯定堆栈是否是跟你同样。以前用Mono包在小米手机上出现过同样的状况,后面改为IL2CPP就没复现了。
感谢剑影蒙残@UWA问答社区提供了回答
A2:楼上这个办法对于部分机型确实有效,不过有些MTK的手机仍是会有相似的问题。咱们项目也有相似的,花屏或者屏幕画面卡死。感受像是Unity合批出的问题,动态合批或者是GPU Instance。咱们尝试着把单个批次的GPU Instance数量下降会有所缓解,这个数量最好根据手机GPU型号作个适配。
感谢Jony@UWA问答社区提供了回答
A3:使用了Unity官方提供的GPU Instance方案来实现的。
https://github.com/Unity-Technologies/Animation-Instancing开始使用的是这个方案默认的Shader渲染了战斗单位,致使了奇怪的闪退和崩溃,默认的Shader以下:
在这个Shader中的loadMatFromTexture函数调用了9次,loadMatFromTexture的实现以下:
能够确认这里的问题大几率是采样次数太多致使,而后修改了就使用当前帧,不进行Lerp操做,且每一个顶点只受两根骨骼的控制,而后测试没有崩溃,目前还正在和美术确认效果损失的接受程度,后来的代码大概是这样:
感谢卢永平@UWA问答社区提供了回答
Q:在Unity UI中,Mask和RectMask性能上有什么区别吗?
A1:RectMask2D:不须要依赖一个Image组件,其裁剪区域就是它的RectTransform的rect大小。
性质1:RectMask2D节点下的全部孩子都不能与外界UI节点合批且多个RectMask2D之间不能合批。
性质2:计算Depth的时候,全部的RectMask2D都按通常UI节点看待,只是它没有CanvasRenderer组件,不能看作任何UI控件的bottomUI。
Mask:组件须要依赖一个Image组件,裁剪区域就是Image的大小。
性质1:Mask会在首尾(首=Mask节点,尾=Mask节点下的孩子遍历完后)多出两个Draw Call,多个Mask间若是符合合批条件这两个Draw Call能够对应合批(Mask1的首和 Mask2的首合;Mask1的尾和Mask2的尾合,首尾不能合。)
性质2:计算Depth的时候,当遍历到一个Mask的首,把它当作一个不可合批的UI节点看待,但注意能够做为其孩子UI节点的bottomUI。
性质3:Mask内的UI节点和非Mask外的UI节点不能合批,但多个Mask内的UI节点间若是符合合批条件,能够合批。
从Mask的性质3能够看出,并非Mask越多越很差,由于Mask间是能够合批的。得出如下结论:
- 当一个界面只有一个Mask,那么RectMask2D优于Mask;
- 当有两个Mask,那么二者差很少;
- 当大于两个Mask,那么Mask优于RectMask2D。
感谢你如暖阳@UWA问答社区提供了回答
A2:从多个Mask合批考虑楼上的结论是能够的,这里补充一下:Mask写Stencil会有额外的OverDraw,Mask2D没OverDraw,但每一个Item都要和MaskRect比较,有必定的CPU开销(Mask适用于Item不少的状况,Item少建议Mask2D)。
感谢羽飞@UWA问答社区提供了回答
A3:从UI合批的角度看,在同一层级中:Mask是一个具备高优先级的特殊组件,会优先进行操做。Mask会改变本身和其中UI的Material,二者不一样。
RectMask2D是一个裁剪器,没有特殊权限,其合批规则与其它普通组件相同。RectMask2D会改变其中UI的Clip Rect。故不在同一个RectMask2D下的UI组件不能合批。
在UI可否合批的缘由中,猜想:
Different Rect Clipping是指从RectMask2D到普通组件,或反之Different Clip Rect是指两个RectMask2D之间切换。
感谢Tao@UWA问答社区提供了回答
今天的分享就到这里。固然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题也许都只是冰山一角,咱们早已在UWA问答网站上准备了更多的技术话题等你一块儿来探索和分享。欢迎热爱进步的你加入,也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。
官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
UWA学堂:edu.uwa4d.com官方技术QQ群:793972859(原群已满员)