【Unity优化】UWA优化小记
【Unity优化】UWA优化小记

【Unity优化】UWA优化小记

【Unity优化】UWA优化建议部分小记

最近刚刚结束了一阶段的UWA优化团队的对接以及对应的项目优化改动,姑且记录一下几个之前一直忽视经过前辈提醒以及具体数据分析开发中忽视的问题

Script相关

在编写一些操作数据结构的代码过程中,因为一些较为机械但是代码量大的数据操作过程中(例如排序,字典遍历取值等),我经常会使用一些linq库提供的较为简洁的api例如ToList(),Distinct,sort等方法,这些方法本质确实能提供较为快捷的一些基础操作,但是实际上由于实现原理的缺陷导致当我们对一些比较数据量大的容器进行linq提供的操作时,产生的gc会成倍增长从而导致峰值热点产生。

例子: 现在有一个List<T>容器里面有一些需要处理的数据,希望借助Distinct移除重复元素,

原先的代码是 

List<T> initialList = new List<T>();

var list = initialList.Distinct().Where(a => a != null).ToList();

这一步原意是希望剔除掉List里的非空重复元素,通过Linq的API可以用一行就解决非常简洁,否则可能需要编写一大串代码进行这一步遍历筛重操作。

但是如果换个角度思考,如果只是希望容器是一个非重复元素的数组,C#本身提供HashSet来达到这个目的,同时如果需要进行对空元素移除可以再额外借助Predicate定义一个判定委托来辅助。因此代码可以改为

HashSet<T> initialList = new HashSet<T>();

Predicate<T> check = a => a == null;

initialList.RemoveWhere(check);

这下会避免LinqDistinct中大量的重复内存分配达到优化的目的

这个问题比较好解决,因为Xlua的特性我们可以在通过标记函数类或者具体方法来手动生成对应的Wrap文件,但是经常会遗漏掉一些只是针对当前类打了标签生成了Wrap文件后,当前类里面引用的其他类字段没有打Wrap从而导致在Lua中使用这个类中这些字段时,会有反射寻找这些字段或者函数的性能开销,比较粗暴的办法可以通过命名空间整体把所有CS文件都打Wrap这样是比较稳妥但是对应的每次打Wrap的时长也特别长,也可以通过[BlackList]等特性标签手动屏蔽掉一些不必要的类总之尽量保证Lua中引用的CS脚本字段函数都要被打进Wrap文件中否则可能就会有不必要的性能开销

由于引擎实现的缺陷,有一些原生方法/字段实际上会造成一些gc开销,需要注意使用或者干脆避免使用。(这里的Unity版本是2020.3.7f1 lts版本)

例如gameobject.name,.tag这些字段本质是内部封装了一个方法每次调用都会有不必要的内存分配,所以尽量避免使用或者如果单纯需要匹配可以尝试替换例如CompareTag()等来达到目的尽量不要直接使用这些字段

如题,在需要使用Spine的情况下一定要让美术记得一bytes输出格式二者在读取IO时产生的开销区别很大,其次尽量把对应图集打在一张图不要分多个图层

工程设置相关

如果我们的项目需要用到碰撞器Collider,无论是2D/3D项目,这一块相关的性能开销也是一个不容忽视的点。在ProjectSetting中,Physics/2D中最下面有一个LayerCollisionMatrix,这里记录了游戏中每个layer层级的物体如果带了相关的collider组件会和哪些其他层级的物体发生碰撞计算,一般这里都是默认全开的,这也是经过前辈提醒发现确实不需要所有选项都勾上,根据项目具体需求改善即可

同理上面的Projectsetting设置Time切页,这里的FixedTimestep代表了我们每次间隔多久Unity会进行一次fixupdate,默认设置也是很高根据具体需求不同一般来说改为下图即可

如题,在默认情况下我们都是以固定的较低的优先级进行加载,如果在异步加载场景时没有其他需要做的事可以适当提高优先级然后在加载完毕的回调中在设置回去,在高性能手机上会有很大的优化

Graphics相关

通过把非UI的3D画面使用一个单独的baseCamera输出RT到UI然后更具性能设置不同调整Rt的分辨率,按照一定比率缩放例如(0.9,0.8)然后在铺满可以一定程度渲染单个像素时候的压力

如题,在项目创建Urp的quality预设时需要新建一个PostPreocessData,然而这个文件在默认Inspector模式里面是没有任何面板序列化的字段的可以通过修改成Debug模式观察到他默认引用的都是Hidden/path下面的Urp原生的shader,其中UberPost这个shader中有大量Pass项目实际用不到可以拷贝一份出来手动注释掉一些无用的pass在手动指定给建立的postdata来达到优化目的

可以根据项目需求,对后处理config进行一个整体Manager管理,然后再创建对应的URPQuality预设来区分不同情况下对应的后处理开关,类似Bloom,景深这类需要多倍采样处理的效果,性能开销比较大可以考虑避免在中低端画质下开启,针对Bloom也可以按照上面一条修改PostData预设Shader中在Uberpost的pass中把highqualityBloom魔改,一般2-4次足以

在UI界面开发过程中,一些效果的实现可能会导致界面overdraw飙升导致这个界面开销很高比较卡顿,常见的就是Text自带的Shadow和Outline组件,这两个组件效果不好不说,各自的overdraw都很高(shadow2X,outline5x)如果界面中类似的Text样式很多可能会导致这个界面每次有元素刷新时,整个界面卡顿很高可以考虑去掉这些效果或者换种做法例如利用shader去实现。同时UI界面特效粒子也是一个导致界面overdraw过多的要点,尽量减少粒子数来实现一些需求,其次就是UI界面尽量避免大量琐碎的小元素Image去组合成一个预期的效果,可以考虑直接在PSD中合并导出一张图来减少不必要的overdraw,对于子物体中layout信息改变频繁的例如Scroll等UI节点可以考虑单独挂一个Canvas减少batch,或者干脆放在同层不要过多的层级嵌套

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注