文/ 王啸予

091622iz88q3zjglr8pwbp.png
下图是按解决方案打出来的动态图集。大图集是在游戏Loading时获得动态图片,然后把这些动态图片渲染到RenderTexture上,用GPU的方式来做可以保证加载的效率。在游戏中,英雄头像使用了一张256x256的RenderTexture,而英雄技能、天赋技能和物品图标使用了一张512x512的RenderTexture。这样一来,技能面板动态图标的消耗从12个DrawCall降低到1个DrawCall。而英雄头像部分,从最多9个DrawCall降低到2个DrawCall,这个结果是因为敌我双方英雄头像使用的材质不同。实际操作中,技能面板的动态图片放在同一个层级里,这样就只有1个DrawCall,上面的蒙板、边框零散图片打成静态图集,在不出现穿插的情况下,UGUI也会协助合批。因此通过这种方式大量减少了DrawCall。后面讲到的一些点其实也用到了动态图集。

091624rk1kuesrtrrrbube.pngHUD Wireframe
091625u1rbwj44qqer6y8l.pngMinimap Wireframe
在UI Mesh的构造函数中可以看到是创建了一个GameObject,附加MeshFilter和MeshRenderer,然后再做一些初始化的工作。重点在于自行填充Mesh的三个Buffer:位置、UV和索引。另外为了避免在运行时重复申请内存,在初始化的时候要申请足够多的顶点。在实际游戏中用到了多个UI Mesh,总体的顶点数大概在3000左右。

091626ad04ddqdrgw4p0ag.png
下图是由Actor调用的代码,BuildQuad是Actor申请数据段,返回Buffer的Index。下面这个是运行时改变顶点位置和UV。所以由于一开始申请了足够多的顶点,在运行时基本是没有UI Mesh Rebuild的消耗。

091627ivwozovoqrvsggob.png
为了在一个UI Mesh里面渲染,必须把图标拼到一个大图里。HUD血条是用UGUI的静态图集来做(下图左图)。而在小地图上由于有动态的图标,包括英雄和信使,以及一些会在小地图上显示的英雄技能。采用动态图集方式,在加载时渲染到一张256x256的大图里。

091637muo7lh70o7k0w20g.png
Nvidia在GDC2003有一篇Batch,Batch,Batch,尤其对MOBA这种CPU负担重的游戏而言,降低DrawCall把物件Batch起来就显得很重要。所以对于OpenGL ES3.0以上的机器来说,既然已经去掉了骨骼,很自然地就要使用GPU Instancing。在物件少的时候GPU Instancing的性能相比起来并没有优势,但是物件多了以后,它的性能曲线更平滑。《小米超神》中,小兵分为近战兵、远程兵、投石车这三类。因为红蓝双方小兵的角色模型一致,但纹理不同,为了相同Mesh只用一个Batch来渲染,我们把纹理压成一张,蓝方在左边,红方在右边,使用UV偏移来采样。那么在Instancing的时候就需要把动画帧、UV偏移、颜色等信息作为数组传入。

091638o6gz1mtgu3q38g52.png
以上就是我本次分享的技术内容,基于《小米超神》研发过程中遇到的问题和解决方法的复盘,希望能对大家的研发有所参考。谢谢大家!

关于UWA:

由侑虎科技开发的游戏/VR应用性能优化平台,目前提供 1)性能诊断与优化 2)资源检测与分析 3)UWA GOT 三大工具,帮助开发者在短时间内大幅度提升性能表现;同时其搭建的知识分享的博客和答疑解惑的互动平台使广大开发者收益。

via:侑虎科技

锐亚教育

锐亚教育,游戏开发论坛|游戏制作人|游戏策划|游戏开发|独立游戏|游戏产业|游戏研发|游戏运营| unity|unity3d|unity3d官网|unity3d 教程|金融帝国3|8k8k8k|mcafee8.5i|游戏蛮牛|蛮牛 unity|蛮牛