一、纹理格式

关于首次打开UI界面时,会进行加载界面上的纹理资源,然后缓存在内存中,下次打开时就直接拿缓存上的资源,所以会比第一次打开快很多,当纹理资源越大第一次打开界面的时间就越长。

平台:压缩格式名词(像素占位个数 纹理尺寸要求 纹理颜色通道要求)

Android平台:ETC1(4bit 必须被4整除 不可带透明通道)、ETC2(8bit 必须被4整除 可带透明通道)、RBA16(16bit)、RBA32(32bit)

IOS平台:PVRTC(4bit 宽高相等且为2的整数次幂)、ASTC5x5(不可带透明通道)、ASTC4x4(8bit 必须被4整除 可带透明通道)、RBA16、RBA32

硬件限制:

Android:ETC2 只支持OpenGL ES 3.0以上(大概2013年之后手机都支持) 

IOS:ASTC只支持苹果A8及以上、iPhone 6及以上(大概2014年之后都支持)

Unity扩展的Crunched压缩,例如RBGA Crunched ETC2是在进行了ETC2压缩后,再次用Crunched方式压缩,纹理会变的更小,虽然解压缩有2次,但是当纹理越大时,由于纹理变得比ETC2压缩更小了,理论上是会比ETC2更快加载出来的。

在IOS上PVRTC通常不适合于压缩带透明通道的纹理,可使用ASTC4x4替换

Unity官方文档说明:https://docs.unity3d.com/2017.1/Documentation/Manual/class-TextureImporterOverride.html

一种在导入贴图时自动处理设置压缩格式的方法:

using UnityEditor;
using UnityEngine;

public class TextureImport : AssetPostprocessor {

    void OnPreprocessTexture()
    {
        if (assetPath.Contains("Assets"))
        {
            TextureImporter textureImporter = AssetImporter.GetAtPath(assetPath) as TextureImporter;
            //设置IOS平台压缩格式
            TextureImporterPlatformSettings settings = new TextureImporterPlatformSettings();
            settings.overridden = true;
            //settings.name = "iPhone";
            settings.format = TextureImporterFormat.RGB16;
            settings.name = "PC";
            //settings.name = "Android";
            textureImporter.SetPlatformTextureSettings(settings);
            Debug.Log("修改导入的贴图纹理压缩格式成功 :ASTC_RGBA_4x4 iPhone IOS平台" + assetPath);
        }
    }
}

二、通道分离

Unity 设置UI界面高宽 unity ui大小_整除

TextureType为

Unity 设置UI界面高宽 unity ui大小_整除_02

压缩格式:RGB Compressed ETC 4 bits情况下,勾选Compress using ETC1 (split alpha channel)

但又提示: Cannot compress to ETC1. The split alpha channel and compression to ETC1 requires a packing tag.

翻译:无法压缩到ETC1。分割alpha通道和到ETC1的压缩需要一个包装标签。这什么意思?

这样处理后Unity会将图片分成2个部分,一个是ETC1的压缩RGB通道,另一个是A通道的图片用的是A8方式压缩。
假设是1024*1024的图片就变成了0.5M + 1M = 1.5M内存占用,要设置A8方式压缩必须将

Unity 设置UI界面高宽 unity ui大小_Unity 设置UI界面高宽_03

Edit->Project Settings->Graphics (打开Graphics面板)

Unity 设置UI界面高宽 unity ui大小_Unity 设置UI界面高宽_04

这个Shader作为包含打包出去的Shader。

然后将游戏发布后用Profiler查看纹理占用内存可见如下图:

三、纹理尺寸

上面纹理压缩格式说到 PVRTC需要图片宽高相同且2的整数次幂,ASTC、ETC都需要被4整除。
若一张图片不满足以上条件时,如果美工很难处理图片变成合适的尺寸,可以使用如下方法:

Unity 设置UI界面高宽 unity ui大小_整除_05

Non Power of 2选项:None(不进行拉伸)、ToNearest(拉伸到最接近的合适尺寸)、ToLarger(往更大尺寸拉伸)、ToSmaller(往更小尺寸拉伸)

下图是我选了ToLarger的情况:

Unity 设置UI界面高宽 unity ui大小_Unity 设置UI界面高宽_06

可以看到图片被明显地拉长了,但是压缩格式符合了ETC要求,因此空间大小变为1MB

2、利用图集尺寸必然满足2的整数幂(也是能被4整除的),将图片标记为图集即可。

Unity 设置UI界面高宽 unity ui大小_Unity 设置UI界面高宽_07

Unity2017有一个叫Sprite Atlas的图集资源,我们也可以用它来打图集 

Unity 设置UI界面高宽 unity ui大小_加载_08

其次,由于我们知道图集是由Unity动态决定大小的,例如有如下选项:

Unity 设置UI界面高宽 unity ui大小_UI_09

Allow Rotation是允许图集的图片能够旋转,勾选后图集大小可能会变小,但是图片的旋转方向会改变,一般都不勾选。
Tight Packing勾选后会根据精灵Mesh轮廓来打包精灵,而不是默认的矩形轮廓来打包(即裁剪小图时会更加精密如果不需要就别勾)
Read/Write Enabled:是否可读写 图集图片; 需要的时候才勾选。
文档:https://docs.unity3d.com/Manual/class-SpriteAtlas.html

四、优化UI方案

1、带分页的界面最好将子页单独作为预制体,标签页单独作为预制体,而不是组合在一起,以减少预制体大小加快加载。

2、界面粒子特效、模型等可以被动态加载出来的元素不要放到预制体中,甚至图片都可以在加载完毕预制体后才进行加载图片

3、将同步加载变成异步加载,异步加载可能会导致玩家感受到突兀,可以利用UI动画来缓和这种感受,大部分游戏都会有UI动画,可以参考它们的来学习。

4、UI加载的图片存在于图集中,会在第一次加载图集的图片时加载整个图集,所以要确保图集不能太大,例如:将宽高大于256的图片从图集移除,尽量保证图集没有空余空间,例如下图图集就有比较大的空余部分造成了空间浪费,并导致了加载界面慢的问题。

Unity 设置UI界面高宽 unity ui大小_UI_10

将比较大的图片从图集移除后,效果如下(可以很明显感受到区别,你加载2M 比我加载256KB肯定是更慢的)

Unity 设置UI界面高宽 unity ui大小_加载_11


5、尽量少用LayoutGroup组件,可自行实现一个。LayoutGroup会考虑元素大小不一样的情况,但是往往我们不需要考虑这种情况所以我们自己可以实现一个简单的仅仅考虑元素大小一样的,这个消耗肯定是比LayoutGroup更小的。而且这个组件算是最常用的UI组件之一。

6、滚动列表的元素可以分帧加载(可以做个无限滚动列表之类的扩展分帧加载功能,当元素比较多的时候选择分帧加载)

针对首次加载超过400ms耗时的UI着重优化,因为这种会影响游戏体验。