Unity项目中UI同学需知的程序相关要点

背景和目的

本文的背景是《独立防线》(Killer)项目已进行到了一定阶段。虽然之前定下了UI制作规范,但中途也更新了规范,但程序和美术没有具体面对面沟通,也没有阐述规范的原因和落地方法。
所以,本文目的是为UI美术同事介绍:1、手游性能相关的标准是什么;2、具体制作时需要注意什么;3、什么样的UI流程是高效的。
注,以下内容并非要求UI美术同学都掌握、或者要求UI美术单独去处理。而是希望UI美术同学能知道有这些一回事需要考虑。最重要的是:在设计之初,能意识到可能有问题,需要找程序去沟通

体验和性能

极端的体验和极端的性能都不现实。

极端的体验

极端的性能(从2015年的标准来看)

在手游平台上,我们应该追求的是体验和性能平衡

体验和性能的平衡

性能评估标准

游戏中,任一元素(UI图片、特效、模型等)对性能的影响都可以拆分为以下4种影响。


影响性能的4大方面

现就UI相关的影响进行举例如下。

CPU消耗

CPU负责把UI界面的逻辑结构进行更新、汇总,并负责把这些数据准备好。最后把这些信息传给GPU。

UI一般影响CPU的因素包括:

  • 界面结构复杂度
  • 界面结构变化频率
  • 动画复杂度
复杂的界面结构

GPU消耗

GPU负责最终画面的绘制、渲染。因为渲染是复杂的流程、且运算量巨大、且手机GPU固有的硬件限制(核心数少、浮点运算速度慢),手游的性能瓶颈往往都发生在GPU。
也就是说,GPU消耗是性能优化的重中之重
UI一般影响GPU的因素包括:

  • 绘制次数(drawcall),和单张图片的数量等因素相关
  • 图片最终在屏幕所展现的面积
  • 图片是否透明
  • shader的复杂度
  • 重绘度(overrdraw,单位像素的重新绘制次数)

其中,特别值得注意的是drawcall重绘复杂度

drawcall

每一个不同“材质”的东西都需要占用一个drawcall。每多一个drawcall必然带来额外的CPU消耗和GPU消耗。


UI界面的drawcall次数为125次

可以简单认为,当两个东西的材质的shader相同,且纹理相同,则它们是同一个材质,在渲染它们的时候,引擎会进行优化,会合并drawcall为1个。

overdraw

overdraw健康的UI界面
overdraw不健康的UI界面

overdraw表示单位像素的重新绘制次数
右部表示overdraw的程度,越“亮”的区域表示overdraw的程度越高,也就越消耗GPU。

外存消耗

外存消耗指的是资源在用户“硬盘里占用了多少多少M”。
如果外存过大,可能导致用户不愿意下载,或者下载安装后,硬盘空间不够,安装不成功。
一般影响外存的因素包括:

  • 图片数目
  • 图片的分辨率大小
  • 图片是否压缩

另外,优化了外存,内存往往也会从中受益。

内存消耗

内存消耗指的是“游戏在实际运行时,占用多少M”。
如果内存过大,可能会导致用户游戏体验不流畅,甚至crash。
一般影响内存的因素包括:

  • 图片数目
  • 图片的分辨率大小
  • 图片的分辨率是否是2的N次方,
  • 图片是否压缩

UI制作要点

UI输出的图片,可在Unity里设置为新的等比缩放分辨率

正因如此,UI美术同学在输出UI贴图时,一般情况下按美术示意图的原分辨率输出即可。


输出图原本的分辨率为788x488

输出图在Unity里被设置为宽高不超过512

单独调分辨率的工作,目前是由开发同学进行。最理想的工作流程,是UI美术同学在导图到Unity的时候,就单独按需设置分辨率(和特效场景模型同学的工作流程一样)。
至于什么情况下需要进行降分辨率操作,见下文。

低频变化的图片的分辨率可以很小

本方法能为GPU、外存、内存带来好处

低频变化的图片指的是纯色的、渐变等变化比较平缓的图片。
低频变化的图片拉伸后仍能表现非常类似的效果,这是因为GPU在图片采样时会进行相邻像素的插值,从而能大概还原之前的平滑度。
总而言之,低频变化的图片的分辨率可以很小。
实例如下。

低频变化图片:原图512x512

低频变化图片:输出给程序的图片缩小为32x32

低频变化图片:程序在使用时将32x32拉伸为512x512

“好”的UI可以拉起“不好的”UI的表现

本方法能为GPU、外存、内存带来好处

“好”的UI可以拉起“不好的”UI的表现

“好”的UI可以拉起“不好的”UI的表现这句话可以有以下的理解:

  • 不压缩的UI可以拉起压缩的UI表现
  • 高分辨率的UI可以拉起低分辨率的UI表现
  • 高频率变化的UI可以拉起低频率变化的UI表现

如上图的放射线部分,它实际是由两张不同的放射线图上下叠加而成。下层的放射线顺时针转动,上层的放射线逆时针转动。
由于上层的放射线作为表现的主体所以采取了“好”的设置(分辨率高、非压缩),那么作为表现的衬托部分的下层图,就算采用比较“不好”的设置(分辨率低,压缩),也不容易察觉。
所以,针对这种多UI同时或同位置出现的情况,可以酌情调低某些UI的设置。
当然,这个例子中,上下两层采取同一张高品质的图也是解决方案之一。

输出图片的分辨率可以酌情低于视网膜的分辨率

本方法能为GPU、外存、内存带来好处

从iPhone4开始兴起了视网膜级别的PPI。这让手机的任意App的任意界面的任意一帧,都看不出任何像素感,提高了App的用户体验。
但在游戏中,游戏有以下特点:

  • 游戏的UI资源是独立原创的(App的UI资源有可能直接使用操作系统自带的资源,节省外存),会带来非常客观的外存、内存消耗
  • 游戏是动态的
  • 游戏的一帧内,最吸引玩家眼前的往往是一个局部
  • 再根据上面提到的“好”的UI可以拉起“不好的”UI的表现

所以在游戏中,可以酌情将特定非重点的UI图片的分辨率降低。


输出图片的分辨率可以酌情低于视网膜的分辨率

继续以上图为例,获得的黄金物品作为表现的主体之一,是视网膜分辨率的。但它下面的弹出框背景作为表现衬托,采取了低于视网膜分辨率也察觉不出。

去除UI图片中不必要的通道、不必要的区域

本方法能为GPU、外存、内存带来好处

去除UI图片中不必要的通道、不必要的区域

如上图。地球UI图片是没必要有透明通道的,因为它一直以整张底图的形式存在于游戏。
地图UI图右部是可以斟酌是否需要存在的,因为它在游戏中一直都被带有背景的排名列表UI挡住。

UI图片一般情况下都不需要mipmap

本方法能为外存、内存带来好处

mipmap会生成多张小图来避免缩小图片时没必要的采样消耗

mipmap会生成多张小图来避免缩小图片时没必要的GPU采样消耗。但使用mipmap的图片会比不使用的图片多占用约三分之一的外存和内存。
由于《独立防线》项目以iPhone4作为目标分辨率进行制作,且认为此分辨率是需支持的最小分辨率,也就是说,UI图片很少有缩小的情况出现,所以《独立防线》项目的UI图片都不需要mipmap,减少没必要的外存、内存消耗。
其他项目如果需兼容更低分辨率的设备,则要按需选择mipmap。

多张UI图片可以打包在一起

本方法能为GPU带来极大好处,但可能为外存、内存带来坏处

操作很简单,选择需要打包的图了之后,在属性面板里键入任意同一英文字符串(比如这里的PackUIBattle)就好了。

在Unity多图打包的方法:在Packing Tag加上英文字符串

这样了之后,多张图被打包在一张图里面。

多张UI图通过SpritePacker的打包结果

由于多张图片打包在了一起,根据上面提过的合并drawcall的原因,会大幅减少这些图片带来的GPU消耗。
但从上图也可以看出,打包之后,会产生多余的透明区域,所以打包可能带来的坏处就是增大了外存、内存。
所以,关键是选择哪些图片进行打包。来规避透明区域的出现。选择规则如下:

  • 不用的图不打包。因为打包的图,就算从不使用,也还是会进入到最终的ipa或者apk里;
  • 小的图尽可能打包
  • 大图(比如大于512x512,常见的有UI底图)不打包。因为大图会很有可能产生透明区域;
  • 降低需要打包中的分辨率最大的图。

不打包的单张UI图片分辨率必须是偶数、很有可能需要是2的N次幂

本方法能为GPU、外存、内存带来好处

按照上面的多张UI图片可以打包在一起做了之后,不打包的图应该是少量的。
但由于这些图是独立存在于内存,所以有更严格的要求:

  • 单张UI图片分辨率必须是偶数。
  • 单张UI图片当有以下任一特点时,分辨率必须是2的N次幂
  • 需压缩的单张UI图片。
  • 需tiled的单张UI图片。tiled即图片平铺,常用于四方连续UI图。
  • 需mipmap的单张UI图片。即多层图片。一般情况下,UI的图片都不需mipmap,所以不用考虑这个。

@程序同学:现在大部分移动设备GPU是支持非2的N次方的。即NPOTSupport.Full或者Restricted的。Full的GPU对任意分辨率的纹理都能直接访问;Restricted的GPU,一般情况下对任意分辨率的纹理都能访问,但对于mipmap、tiled的纹理会把它pad成POT。
所以,mipmap、或tiled的非打包单张纹理需强制POT
笔者身边的红米、三星、华为等手机,都支持NPOTSupport.Full,只发现小米3支持NPOTSupport.Restricted,小米3W支持NPOTSupport.Full。

@程序同学:
ETC1(4bit/pixel)成功压缩要求不带透明通道(ETC1的编码block为4x4像素,ETC1编码时会自动把分辨率补为4的倍数),否则将以16bit/pixel的方式压缩保存;PVRTC成功压缩的要求是POT且方形,否则将以true color(32bit/pixel)不压缩保存。常用的方案是,把UI图片打包到一张大图,且大图同时满足ETC1和PVRTC的要求,即POT、且透明通道拆分到大图的下半部、且方形。
这需要有特殊的shader对这张大图进行采样:RGB取原本uv、A取uv向下偏移0.5。下半部的Alpha部分可以把Alpha值除以3平均分部到RGB通道,采样时把RGB相加作为Alpha,这样有利于ETC1压缩的效果。
因大图的制作需要上半部是UI图片的RGB部分、下半部是UI图片的Alpha部分。所以需要自研或获取适合的atlas算法对UI图片进行排版。此时上面提到的Unity自带的Sprite Packer方法将不再适用。
排版后的大图的可容忍浪费分辨率是原图的16bit/4bit=4倍,或32bit/4bit=8倍。
注,PVRTC本可不拆Alpha,以RGBA4bit压缩,但这样往往UI纹理视觉效果太差。所以PVRTC可以也拆分Alpha,以“RGBA8bit”=RGB4bit+RGB4bit方式压缩,视觉效果可以接受。而且这样恰好和ETC1纹理的流程一致。即ETC1和PVRTC的结果是都拆Alpha,但它们拆Alpha的原因不一样。

打包的UI图片的分辨率可以是任意的

但依然推荐输出偶数分辨率,避免未来带来不可知的麻烦。

UI最好能用九宫格+局部装饰实现

本方法能为GPU、外存、内存带来好处

Unity UGUI支持直接使用Sprite Editor直接进行九宫格制作

九宫格已经是非常常用的UI制作方法。
九宫格UI几乎是百利无一害,所以希望UI同学能用九宫格的尽量用九宫格。
使用九宫格有以下几个值得注意的技巧:

  • 九宫格UI图片可以做得很小只给正方形的图,而并非上面一个长条形的图
  • 如果UI图片内部是低频变化(人话:比较平滑的纹理),依然可以使用九宫格
  • 如果UI图片内部是高频变化(人话:比较细的复杂纹理),一般情况下就不能使用九宫格了
  • 但可以把这些高频变化的纹理设计成只在边缘出现,让九宫格十字架内依然是低频变化,那这种UI图依然可以九宫格
  • 切九宫格时,边缘部分应尽量细、内部十字架部分应该尽量饱满。这样可以确保这个UI能够使用于非常小的场合而不穿帮

字体选择方案

本方法能为外存、内存带来好处,可能为GPU带来好处

在选择游戏字体的时候,除了确保美观程度之外,还需考虑:

  • 字体种类:应当保持在2类以内:用于标题的中文偏设计的字体、用于正文的中文偏正式的字体。如需,可额外加入英文偏设计的字体;
  • 字体编码类型:如果是中文字体,需考虑是否GB2312编码甚至是GBK编码。避免字体出现有些常用中文字没有的情况;
  • 在选择字体时,应留意在手机上的表现。比如一些字体比较细,在手机上看不清,到后面需要都加粗加描边,带来没必要的消耗,也带来了之后额外的繁琐的字体相关工作。
由于选择了细字体,导致在手机上需要都加粗加描边,带来没必要的消耗(比如overdraw)

制作流程

UI同学和程序同学一起维护Unity UI资源文件夹

当前的工作流程是美术同学输出了UI图片后,传到FTP,通知程序同学具体路径,程序同学从FTP拷贝资源到UnityUI资源文件夹,为了版本一致,程序同学可能需要对它进行重命名,才用上了一张新资源。

Unity UI资源文件夹里存放着真正采用到游戏的文件夹
这个文件夹事实上已经存在了,但只有程序同学在维护。现在需要UI美术同学、程序同学一起来维护它。
这样有以下好处:

  • Unity的文件夹里,可以直接存放任意格式的图片甚至是psd。Unity在构建时才将这些图片转为需要用的格式
  • 可以直接在Unity看到图片在手机里内存、外存的真正占用
  • 方便查找真正在用的UI资源
  • 由于这个文件夹的资源是正式且确保资源不重复,所以方便美术同学间协作,防止信息不对称制作了重复资源
  • 当有UI小幅修改时,美术直接修改即可。而不是走一个美术修改、传给程序、程序替换的臃肿流程
  • 给资源重用落地提供基础

事实上,我们的特效、场景、模型都已经是这样做了,一起维护一个真正采用到游戏的文件夹

资源组件重用

老生常谈、不得不谈。
资源重用可以节省策划同学工作量、美术同学工作量、程序同学工作量,节省外存、内存,也节省用户体验学习成本,。
如果减法百利无一害,何必狂做加法吃力不讨好。

Flash项目可重用贴图的资源库

Unity项目可重用贴图的资源库

一个可以帮助资源重用的思考流程大致是这样的:

  1. UI美术同学如果在接到新UI需求;
  2. 先想UI的某个组件能不能用资源库里已有UI资源组件来完成
  3. 如果能,则重用,仅仅在Photoshop里制作示意图,不输出该UI组件资源(此时,如果可以形成工具和规则,帮助UI美术同学将psd导出成prefab,将有效提高UI合入效率。《独立防线》项目组正在往这个方向尝试);
  4. 如果不能,才设计新UI组件资源;同时,新资源也遵循可重用规则;
  5. 新资源归档回资源库;
  6. 多次重复1-5步后,资源库会越来越容易满足未来的新UI的需求。

适配设备分辨率的UI制作思路

接近16:9的iPhone5(1136 x640)的关卡界面
接近1:1的iPad Retina(2048x1536)的关卡界面

最近新出的手游为了更好的体验,都采取了填满设备屏幕的分辨率适配的UI方案。所以要求策划同学、UI同学在设计时,就要考虑分辨率适配问题。而并不能仅仅瞄准一款热门设备比如iPhone5进行设计。

Unity UGUI有很好的UI适配方案。概括描述如下:

矩形的原点都在左下角。
3个重要的矩形:实在存在的父矩形、用于辅助的anchor矩形、实在存在的子矩形(当前矩形)
父矩形内部包含了anchor矩形和子矩形。

下列图中,外框表示父矩形、“四叶花瓣尖”组成anchor矩形、蓝点表示子矩形。

图:anchor矩形四角跟父矩形四角一一对应。即归一化距离(即距离占父矩形宽或高的比例)固定。对应的两个角之间就好像用**橡皮筋**绑起来一样。比如图中左上花瓣跟左上角距离总是50%宽、60%高。注意到,图中anchor矩形四角聚在一起,这样父矩形大小变化时,anchor矩形大小不会变化。
图:anchor矩形四角跟父矩形四角一一对应。对应的两个角之间的归一化距离(即距离占父矩形宽或高的比例)固定。对应的两个角之间就好像用**橡皮筋**绑起来一样。比如图中左上花瓣跟左上角距离总是10%宽、50%高。注意到,图中anchor矩形四角各自分开,这样父矩形大小变化时,anchor矩形大小也会变化。
图:子矩形四角跟anchor矩形四角一一对应。对应的两个角之间的距离固定。对应的两个角之间就好像用**铁棒**锁起来一样。比如图中左上蓝点跟左上花瓣的距离总是80像素宽、30像素高。注意到,图中anchor矩形四角聚在一起,这样父矩形大小变化时,由于anchor矩形大小不会变化,所以子矩形大小不会变化。
图:子矩形四角跟anchor矩形四角一一对应。对应的两个角之间的距离固定。对应的两个角之间就好像用**铁棒**锁起来一样。比如图中左上蓝点跟左上花瓣的距离总是40像素宽、20像素高。注意到,图中anchor矩形四角各自分开,这样父矩形大小变化时,由于anchor矩形大小也会变化,所以子矩形大小也会变化。

总之,anchor矩形四角跟父矩形四角一一对应,对应的两个角之间的归一化距离(即距离占父矩形宽或高的比例)固定;子矩形四角跟anchor矩形四角一一对应。对应的两个角之间的距离固定。

通过这样的关系,就可以实现各种不同的适配方案。比如以下这些。

当四花瓣聚在一起时,父矩形改变大小,子矩形大小不会改变。位置会锁定在归一化距离。


横向纵向皆不拉伸

当四花瓣格子横向分开时,父矩形改变大小,子矩形横向大小会相应改变。


横向拉伸、纵向不拉伸

当四花瓣格子横向纵向皆分开时,父矩形改变大小,子矩形横向纵向大小皆会相应改变。


横向纵向皆拉伸
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容