一:图集介绍

什么是图集:我们可以将其理解为将一系列小图合并为一张大图。使用图集可以减少drawcall,提升效率。 ​ 游戏中的图片模型最终是要给到显卡去渲染的,然后CPU通知GPU要开始渲染,这一次通知就是一次Drawcall。当一个UI里面图片非常多的时候,我们可以使用图集技术将其一次性渲染。

Unity打包图集的方式有很多种,这里我们讲解三种:

(1)一种是使用系统自带的打包工具SpritePacker;

(2)使用SpriteAtlas进行打包图集

(3)使用TexturePacker打包图片并使用;

二:SpritePacker使用

1、将所需要的图片导入Unity中,注意不能放在Resources文件夹下(图片将不能被打包成图集);

2、选择需要打包成图集的图片(可以多选)在inspector面板里选择“Texture Type“为“Sprite (2D and UI)”,并Apply应用;

3、在”Packing Tag”选项里面填上图集的名称,该选项相同的图片会打包为同一个图集;

4、选择菜单栏里面的 "Edit" -> "Project Settings" -> "Editor"; 5、在inspector面板里设置“Sprite Packers”下面的“Mode”选项,其中,“Disabled”表示关闭图集功能,“Enabled for Builds”表示打包发布时才打包图集,“Always Enable”表示始终打包图集;Enabled for Builds(Legacy Sprite Packer)表示打包发布时才打包图集(使用旧版技术);“Always Enable(Legacy Sprite Packer)”表示始终打包图集(使用旧版技术)

6、设置完上述选项后,选中需要打包图集的图片,在 “Window ” -> “Sprite Packer”面板里预览图集,可尝试点击左上角的“Pack”按钮立即打包;

不同图片如何合并至一个图集?

  • 选中需要打包图集的图片,将其类型修改Sprite (2D and UI),修改其Packing Tag为你自定义的名字。不同的图片,只要Tag相同,就可以打包到同一个图集里面。

打图集策略:

(1)DefaultPackerPolicy:是默认的打包方式,也是矩形打包方式。他会把所有的小图按照矩形的方式来排列,如果宽高不一样的图片,它们会自动补齐,使用方式就是tag设置时加上”[RECT]图集名”来设置。

(2)TightPackerPolicy:是紧密打包方式,也就是尽可能的把图片都打包在图集上,这种方式要比DefaultPackerPolicy打包的图片更多一些,也就是更省空间,使用方式就是tag设置时加上”[TIGHT]图集名”来设置。

(3)TightRotateEnabledPackerPolicy:是紧密可旋转打包方式,也就是使用紧密打包,并且允许精灵进行旋转。

(7)设计UI,几个Image使用同一个图集的不同元素,发现四个Image一次性渲染成功。

三:SpriteAtlas使用

Sprite Atlas 针对现有的图集打包系统Sprite Packer在性能和易用性上的不足,进行了全面改善。除此之外,相比Sprite Packer,Sprite Atlas将对精灵更多的控制权交还给用户。由用户来掌控图集的打包过程以及加载时机,更加利于对系统性能的控制。设置Edit-->Project Settings -->Editor --->Mode为Always Enable。

Sprite Atlas的主要有以下三个功能:

1.创建、编辑图集以及设定图集参数

2.添加图集Variant(变种)

3.运行时访问图集

下面我们分别讲解

3.1 创建、编辑图集及参数设定

在Unity 2017.1版本之后,SpriteAtlas是一种资源,右击 Asset ---> Create --->SpriteAtlas 可以像其它资源一样在Unity中创建,例如预制件、场景等。

这里可以支持多种类型,包括单个Sprite、Sliced Sprite、文件夹,以及这些类型的任意组合。

操作更加方便,对用户更友好。可以将文件夹,纹理或精灵分配给Sprite Atlas。可以将整个文件夹分配给Sprite Atlas资产,该文件夹中的所有纹理(包括子文件夹)都将被打包,使用起来非常方便。

此外,在检视窗口上还可以看到图集的一些参数设定,例如:打包时是否支持精灵旋转(Allow Rotation)、贴图的采样模式(Filter Mode)、压缩方式(Compression)等等。 ​ 在最下方的预览窗口中,可以查看图集的生成效果。这样就可以很清楚的知道图集的打包方式是否合理,是否存在大量被浪费的空间。

设计UI,添加几个Image,使用SpriteAtlas图集内部的图片作为Image原图片,发现DrawCall只需要一次就可以完成。

2.添加图集Variant(变种)

所谓Variant,就是指原有图集的一个变种。它会复制原有图集的贴图,并根据一个比例系数来调整复制贴图的大小。

这样的Variant通常用于为高分辨率和低分辨率的屏幕准备不同的图集。

因为如果只准备一套高分辨率的图集,在低分辨率的设备上占用内存过多。反之,如果只准备一套低分辨率图集,在高分辨率的设备上就会模糊。

通过Atlas Variant就可以很方便地解决该问题。如下图所示,SpriteAtlas .spriteatlas是新建的一个低清图集,在检视窗口中将Type设为Variant,Master Atlas设为SpriteAtlas。这里为了与原图进行更明显的对比,将Scale设为0.1, 点击Pack Preview。

3.运行时访问图集

我们经常会在代码中切换ui的图片,所以就需要单独加载图集中的每个精灵。

这样做的好处是,让用户可以更加直接地随时编辑图集,而且不用去单独加载图集中的每个精灵。

下面是一段动态换装的代码,该脚本通过LoadAsset加载SpriteAtlas类型的资源,再通过SpriteAtlas的GetSprite接口获取图集中的精灵,最后将精灵传递给SpriteRenderer。相较于基于Sprite Packer的实现,整个过程要简单直接的多。

using UnityEditor;
using UnityEngine;
using UnityEngine.U2D;
​
public class SpriteAtlasExample : MonoBehaviour
{void Start(){void Start(){//加载图集SpriteAtlas atlas = AssetDatabase.LoadAssetAtPath<SpriteAtlas>("Assets/Hero.spriteatlas");//获取图集下的所有SpriteSprite[] sp = new Sprite[atlas.spriteCount];atlas.GetSprites(sp);print(sp.Length);//根据小图名称获取对应的SpriteSprite sprite = atlas.GetSprite("nxxg");if (sprite != null){GetComponent<SpriteRenderer>().sprite = sprite;}}}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.U2D;
​
public class SpriteAtlasMgr : MonoBehaviour
{public static SpriteAtlasMgr instance;private void Awake(){instance = this;}public Dictionary<string, SpriteAtlas> atlas = new Dictionary<string, SpriteAtlas>();public void AddSpriteAtlas(string name) { //}public void RemoveAtlas(string name) {//}public Sprite GetSpriteFromAtlas(string sname) {//....return null;}public Sprite GetSpriteFromAtlas(string atlasname, string sname){//....return null;}// public static SpriteAtlasMgr// Start is called before the first frame updatevoid Start(){}
​// Update is called once per framevoid Update(){}
}
​

四:TexturePacker使用

(1)使用Texture Packer打包图集时,需要将小图导入Texture Packer,然后进行打包,打包的格式要注意是"Unity - Texture2D sprite sheet"(有一些低版本的TP是没有这个格式的),TexturePacker官网:https://www.codeandweb.com/texturepacker。 下载最新版本安装即可

(2)将图片或者文件夹拖动至空白处,设置导出的图片名字以及数据文件。

(3)点击右上角【发布精灵表】,不用作其他修改,将这两个文件放在工程资源中,这时从工程看这只是一张大图,并不能算是一个图集,使用里面的小图(这时虽然可以用unity3d自带功能,手动对图片进行裁剪,但裁剪的小图大小基本是不对的)。

(4)接下来需要下载并导入一个Unity3d的插件,TexturePacker自己出的的一个插件(TexturePacker Importer),插件链接:https://www.assetstore.unity3d.com/en/#!/content/16641,下载并成功导入之后,不用写任何代码,也不用做任何操作,插件会自动根据.tpsheet文件,将刚才打包好并导入工程的大图自动裁剪成小图,如下图所示:

我们只需像使用单独小图一样,将图集里的小图拖进Source Image里即可。这时我们还只能在编辑器里使用图集。

5、有时候,我们还需要在程序中动态加载图集并使用图集里的小图。unity3d 并没有明确api说明我们如何用这种图集,而常用Resources.Load()加载只能返回单独的一个图片纹理,所以我们用另一个方法 Resources.LoadAll();加载整一张图集,此方法会返回一个Object[],里面包含了图集的纹理 Texture2D和图集下的全部Sprite,所以我们就可以根据object 的类型和名字找到我们需要的某张小图片。

6、下面整理了图集纹理的管理类,去统一管理加载,是一个单例类,找个不被销毁的GameObject绑定就行, 代码比较简单,用一个Dictionary按图集的路径过key将加载过的图集缓存起来,需要时再由外部删除掉,如下代码所示:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
​
//纹理图集加载管理
public class TextureMgr : MonoBehaviour {
private static GameObject m_pMainObject;
private static TextureMgr m_pContainer = null;
​
public static TextureMgr getInstance(){if(m_pContainer == null){m_pContainer = m_pMainObject.GetComponent<TextureMgr> ();}  return m_pContainer; } ​private Dictionary<string, Object[]> m_pAtlasDic;//图集的集合 void Awake(){ initData (); } private void initData(){ TextureMgr.m_pMainObject = gameObject;m_pAtlasDic = new Dictionary<string, Object[]> ();}//加载图集上的一个精灵public Sprite LoadAtlasSprite(string _spriteAtlasPath,string _spriteName){Sprite _sprite = FindSpriteFormBuffer (_spriteAtlasPath,_spriteName);if (_sprite == null) {Object[] _atlas = Resources.LoadAll (_spriteAtlasPath);m_pAtlasDic.Add (_spriteAtlasPath,_atlas);_sprite = SpriteFormAtlas (_atlas,_spriteName);}return _sprite;
​
}
​
//删除图集缓存
public void DeleteAtlas(string _spriteAtlasPath){if (m_pAtlasDic.ContainsKey (_spriteAtlasPath)) {m_pAtlasDic.Remove (_spriteAtlasPath);}
}
//从缓存中查找图集,并找出sprite
private Sprite FindSpriteFormBuffer(string _spriteAtlasPath,string _spriteName){if (m_pAtlasDic.ContainsKey (_spriteAtlasPath)) {Object[] _atlas = m_pAtlasDic[_spriteAtlasPath];Sprite _sprite = SpriteFormAtlas(_atlas,_spriteName);return _sprite;}return null;
}
​
//从图集中,并找出sprite
private Sprite SpriteFormAtlas(Object[] _atlas,string _spriteName){for (int i = 0; i < _atlas.Length; i++) {if (_atlas [i].GetType () == typeof(UnityEngine.Sprite)) {if(_atlas [i].name == _spriteName){return (Sprite)_atlas [i];}}}
​Debug.LogWarning ("图片名:"+_spriteName+";在图集中找不到");return null;}
}  

使用代码如下:

public class LoadImage : MonoBehaviour
{public Image parrotImage;// Start is called before the first frame updatevoid Start(){Sprite _sprite = TextureMgr.getInstance().LoadAtlasSprite("parrot", "hlb23");parrotImage.sprite = _sprite;}
}

Unity UGUI图集专题相关推荐

  1. Unity UGUI图集打包与动态使用(TexturePacker)

    TexturePacker 在用UGUI时,我们需要将一个个小图打包成图集,然后将图集一次性加载以内存换取图片读取效率,即减小Drawcall. UGUI打包并使用图集有两种方法:一种是使用系统自带的 ...

  2. Unity打包AssetBundle自动分析资源依赖关系(包括UGUI图集打包)

    https://blog.csdn.net/u012740992/article/details/79371986 怎么分析资源的依赖关系呢,并设置AssetBundleName呢? 我们检测资源之间 ...

  3. 【游戏开发实战】Unity UGUI Text图文混排(聊天文字混表情),支持动态表情,出招吧表情帝

    文章目录 一.前言 二.最终效果 三.具体使用 1.导入表情素材 2.设置图片格式 3.生成表情图集 4.UI-EmojiFont.shader 5.材质球 四.测试 五.结束语 一.前言 点关注不迷 ...

  4. Unity UGUI Rect

    Unity UGUI Rect rect.x与rect.y rect.min和rect.max rect.center rect.x与rect.y x,y就是rect类的根坐标,有了它我们就能确定我们 ...

  5. Unity UGUI Button 中文详解-Chinar

    Chinar blog :www.chinar.xin Unity UGUI 完整系列教程 (Chinar中文图解) Unity UGUI Button 组件 本文提供全流程,中文翻译. Chinar ...

  6. Unity UGUI Batches合批规则详解(含源码)

    Unity UGUI Batches合批规则详解 在处理UGUI DrawCall问题的时候,我们经常遇到各式各样的问题. 问题1:在处理UGUI合批的时候,发现了一个面板父节点发生旋转,底下的UI合 ...

  7. Unity 打包图集

    Unity打包图集 public class MyTexturePak {private const string intPutPath = "/Emoji/Input/";pri ...

  8. Unity UGUI实现图文混排

    目前在unity实现图文混排的好像都是通过自定义字体然后在文本获取字符的位置,用图片替换掉图片标签,这样对于支持英文来说,并没有什么影响.然后对于中文来说就是一个相当麻烦的事了,毕竟图文混排多用于游戏 ...

  9. Unity UGUI图文混排源码(二)

    Unity UGUI图文混排源码(一):http://blog.csdn.net/qq992817263/article/details/51112304 Unity UGUI图文混排源码(二):ht ...

最新文章

  1. 4.4.4 Factory方法
  2. Microsoft SharePoint Server 2016 部署文档(2)
  3. cocos2dx[3.2](5) ——入口类AppDelegate.cpp
  4. LINUX :标准c库
  5. 字符串匹配算法(三):KMP(KnuthMorrisPratt)算法
  6. win7系统临时文件夹的打开方法
  7. jQueryEasyUI框架 - panel 选项卡高度自适应
  8. numpy中数组的简单运算以及使用
  9. dockerfile构建镜像
  10. Android点赞头像列表
  11. ToolBar控件详解
  12. Okhttp之同步和异步请求简单分析
  13. JDK8 官方下载地址
  14. pin与抓握手包破解wifi密码
  15. ucinet计算聚类系数大于1怎么办_UCINET 6
  16. 使用SharePoint Framework开发webpart的一些技巧汇总
  17. 涉密打印机与设密计算机之间采用,涉密打印机与涉密计算机之间 - 作业在线问答...
  18. 他如何从一位专车司机成功变身CEO?
  19. 计算机自带的科学计算器代码,[置顶] 科学计算器(简化版:基于MFC对话框)
  20. 椭圆曲线标量乘法快速算法(附源码实现)

热门文章

  1. excel 两组数据交点_数据分析入门:8种常用的数据分析方法
  2. 《微信公众平台与小程序开发——从零搭建整套系统》——第1章,第1.2节微信公众平台...
  3. 正则表达式: 以英文字母开头,只能包含英文字母、数字、下划线
  4. 【数理统计】调和平均值
  5. 一起来看流星雨剧情简介/剧情介绍/剧情分集介绍第二集
  6. ubuntu11.10 华为无线上网卡e303s
  7. 直播短视频带货完美运营APP源码 购物直播交友系统源码
  8. .NET获取硬盘序列号的几个方法
  9. 都说it是吃青春饭的,那些35岁左右的it女技术人员(测试)都在做啥呢?转行了吗?
  10. 数据库基础:IndexedDB