- 减少射线频率、长度、layer;
- 善用 Physics Matrix;
- 不要移动静态 Collider,需要移动的话加 RigidBody;
- 尽量使用简单的 Collider 替代 MeshCollider;不同类型进行碰撞检测的相对成本是按照以下顺序排序的,从最耗费资源到最不耗费资源:三角形网格、凸包(三角形网格)、胶囊体、球体、立方体、平面、点。
- 一定要控制好 FixedUpdate 的频率,1s 建议不要执行超过30次,因为是 FixedUpdate 执行 Physics,如果 Update 卡顿,会导致 FixedUpdate 执行多次,继而 Update 更加卡顿形成恶性循环;
- 文件压缩,去除无用通道比如 Scale,降低精度保持两位有效小数,设置数值范围压缩数据等;
- GPU 加速动画播放; 更多细节 GPU 加速动画渲染方案
- 开启 Unity 的优化选项;
- 减少关键帧;
-
运行时根据摄像机距离以及手机性能进行 LOD;
-
降低屏幕分辨率;
-
Unity地形贴图数量以及贴图法线(转换成Mesh,然后切割,减少贴图数量、使用Texture2DArray);
-
Using ASTC Texture Compression for Game Assets;
-
一般情况下 Shader 使用低精度代替高精度;
-
遮挡剔除&距离剔除&平截头体剔除; 更多细节 基于大地图的遮挡剔除优化方案
-
开启 Unity 的 Mesh optimizing优化选项;
-
优先使用 Vulkan API;
-
针对老机型(OpenGL ES 2.0),使用 ETC1 和 alpha 两张图保存 PNG图片(带有 alpha 通道的图片);
-
慎用 PBR,场景内大部分物件可以使用简单的 PBR,主角等重要物件使用复杂 PBR 渲染;
-
使用 lightmap,如不行的话,如果物件之间不能批处理的话(不同材质),那么烘焙代理网格处理实时阴影,解决阴影 drawcall 太多的问题; 更多细节 ShadowMeshProxy Plugin
-
可程序化粒子特效(可剔除),尽量程序化,如何避免不可程序化;
-
静态批处理场景物件;
-
动态批处理角色身上的物件,比如武器等,减少 drawcall;
-
石头、树木、草丛等使用 GPU Intancing;
-
移除不需要动画的物件身上的空动画组件;
-
关闭不要接受阴影的物件的接受阴影设置;
-
减少OverDraw,a,大型物件放到渲染队列的末端比如天空盒、地形等;b,减少使用Alpha Blending、Transparency;
-
Camera 设置为 Clear Camera;
-
GPU Upload(Asynchronous Texture Upload) 设置 Time-Slice 以及 Buffer Size;
-
减少 Shader 变体,减少 pass;
-
Shader warm up;
-
场景材质图集合并;
-
大地形设计&优化,这个比较复杂,具体说一下:
切块(Tile)比如32x32。每个 Tile 分层。地表、LOD0(大型建筑物比如房子)、LOD1(小型物件比如桌子、椅子)、LOD2(很细节物件比如花花草草)、Dynamic(场景动画、特效)。 根据英雄所在位置加载周围 Tile,根据分层信息加载显示或者隐藏Tile物件。 场景分区域包围盒,根据距离判断是否卸载某个区域资源。 包围盒设计的大一点以及包围盒可重叠,可重叠为了处理一些特殊情况。单一用距离判断会有瑕疵。比如在城墙外,即使隔的很近也不需要加载城内的细节。而我们完全可以在城门外加一个缓冲的小区域并入城市区域,只要玩家一踩到城门口,城内的细节加载流程就开始启动了。 一个区域物件分细节和外观物件两种,离一个区域较近时就应该开始加载外观物件同时卸载细节物件。比如一片树林是外观物件而地上的花花草草则是细节物件。 手机内存应用一般可以500M,一定要控制在350M以内。
-
正确应用纹理压缩可提供显着的性能优势。在较新的移动设备上,使用 ASTC 压缩的纹理格式。如果目标设备上没有 ASTC,在 Android 上使用 ETC2,在 iOS 上使用 PVRTC;
-
一个角色一般三种贴图 Diffuse + Normal + PBR(Metal + Roughness + AO),尺寸512、512、256;
- 编译设置成 IL2CPP,运行效率较大提升;
- 缓存协议字节数组;
- 使用 ByteArray(定长)替代 ByteList(不定长),尽量用 short 替代 float;
- Nagle 算法,通过减少小的消息发送,来减少网络阻塞;
- KCP 算法,不丢包的 UDP。本质上是 UDP,当成 TCP 来用;
- 尽量缓存计算结果;
- 使用四叉树、八叉树等管理场景物件,控制逻辑频率以及渲染频率(动画等);
- 使用重要度系统(物件的屏占比)管理场景物件,控制控制逻辑频率以及渲染频率(动画等);
- 使用管理器管理物件的 Update 和 FixedUpdate,替代 Unity 自带的 Update、FixedUpdate 的函数,提高性能;
- 使用多线程加速热点逻辑计算;切记不要滥用多线程,应该先优化该热点逻辑,然后移至多线程;
- 资源销毁,分帧处理;
- GC 优化,减少匿名函数使用等;字符串操作是万恶之源!!使用 stringbuilder 或者重写 unity 的 string 解决这个问题;
- 实现重要度管理系统(SignificanceManager),根据对象的距离、面向、屏幕占比等来优化性能,比如降低TICK、LOD、控制特效播放等; 更多细节 重要度管理系统方案
- 网络同步算法:帧同步、状态同步、物理同步
- 更细致的对象池处理;比如基于视野的对象池,如果对象在角色背后,但是在玩家 AOI 逻辑内,逻辑保持运行,显示层直接回收,给其他在玩家视野里的对象使用,最大化缓冲池作用;
- 使用离线的遮挡剔除替代 Unity 遮挡剔除,节省内存; 更多细节 基于大地图的遮挡剔除优化方案
- 使用 LOD 加载远距离的物件;
- 堆内存优化,比如使用定长数组,减少实例化等等;
- 注意各种资源的格式设置比如mp3等;
- 使用引用计数管理 AssetBundle,防止泄露;
- 控制好贴图尺寸,1k 贴图比 512 贴图,因为 mipmap 的原因内存要占用多很多;
- 优先使用 ASTC 压缩;
- 动静分离,减少 UI Overdraw;
- 如果 GPU 在绘制 UI 时时间花费过多,帧调试器指示片段着色器遇到了瓶颈,那么UI很可能是超越 GPU 承受范围的像素填充率;
- 关闭不需要UI交互 Graphics Recast;
- 隐藏和显示UI最好使用开关 Canvas 的方式;
如何判断一部手机性能好坏? CPU,获取 CPU 数量以及最大同时运行 CPU 数量计算出一个值 GPU,根据不同厂商(nvidia geforce,tegra 等等)GPU型号解析计算出 GPU 的 version(枚举出所有型号的比如填充率,三角形渲染效率等,检测不到的GPU认为是高版本) 特殊机型特殊处理,比如小米 特殊情况特殊处理,比如系统内存小于 1G,或者 cpu、gpu 某一项分太低 安卓和 IOS 分开处理 综合以上得出一个总分。
调试工具 WeTest Adreno Profiler Unity Profiler Unity FrameDebugger