一、制作图集的好处:
众所周知CPU是用来处理游戏的逻辑运算的,而GPU是用来处理游戏中图像的。在GPU中,我们要绘制一个图像需要提交图片(纹理)到显存,然后再进行绘制(在这个过程中会产生一次DrawCall),也就是说我们要绘制100张图片就要产生100次DrawCall.显然这是非常消耗性能的。这是制作图集的好处就显而易见了:
①、减少性能消耗,提高处理效率
②、可以归类不同模块的图片
③、一次加载或者卸载完成多图片的处理,提高了运行效率
二、打包图集需要的工具
我们经常听说是在NGUI中打包图集,在用UGUI时,我们也需要将一个个小图打包成图集,以减小Drawcall(类似coco2d-x一样,打包成图集一次性加载以内存换取图片读取效率),UGUI打包并使用图集有两种方法:
一种是使用系统自带的打包工具SpritePacker;
一种是使用外部插件TexturePacker打包图片并使用;
关于第一种方法有另一个文章为大家讲解,另一种熟悉的方法用TexturePacker工具打包,也是本文下面要讲解的本文所使用的是Unity 2018.2.5f1 (64-bit)版本,TexturePacker 5.2.0版本最新版本
1、先用TexturePacker
打小图打包成我们所需要的图集,打包的格式要注意是"Unity - Texture2D sprite sheet"(有一些低版本的TP是没有这个格式的。具体使用方法可以浏览下面的网站https://www.codeandweb.com/texturepacker/documentation
2、打包之后会有一个.png和一个.tpsheet,不用作其他修改,将这两个文件放在工程资源中,这时从工程看这只是一张大图,并不能算是一个图集,使用里面的小图(这时虽然可以用unity3d自带功能,手动对图片进行裁剪,但裁剪的小图大小基本是不对的)
3、接下来需要下载并导入一个Unity3d的插件,TexturePacker自己出的的一个插件(TexturePacker Importer),插件链接https://www.assetstore.unity3d.com/en/#!/content/16641,下载并成功导入之后,不用写任何代码,作任何操作,插件会自己根据.tpsheet,将刚才打包好放进入工程的大图自动裁剪成小图,如下图,打图集点开
我们只需像使用单独小图一样,将图集里的小图拖进Source Image里即可。这时我们还只能在编辑器里设置使用图集。
4、我们还需要在程序中动态加载图集并使用图集里的小图,才算是完整的。unity3d 并没有明确api说明我们如何用这种图集,而常用Resources.Load()加载只能返回单独的一个图片纹理,所以我们用另一个方法 Resources.LoadAll();加载整一张图集,此方法会返回一个Object[],里面包含了图集的纹理 Texture2D和图集下的全部Sprite,所以我们就可以根据object 的类型和名字找到我们需要的某张小图片。
5、下面写了一个图集纹理的管理类,去统一管理加载,是一个单例类,找个不被销毁的GameObject绑定就行, 代码比较简单,用一个Dictionary按图集的路径过key将加载过的图集缓存起来,需要时再由外部删除掉,下面是代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
public class PPTextureManager : MonoBehaviour
{
private static GameObject m_pMainObject;
private static PPTextureManager m_pContainer = null;
public static PPTextureManager getInstance()
{
if(m_pContainer == null)
{
m_pContainer = m_pMainObject.GetComponent<PPTextureManager>();
}
return m_pContainer;
}
//图集的集合
private Dictionary<string, Object[]> m_pAtlasDic;
private void Awake()
{
initData();
}
private void initData()
{
PPTextureManager.m_pMainObject = gameObject;
m_pAtlasDic = new Dictionary<string, Object[]>();
}
//加载图集上的精灵
public Sprite LoadAtlasSprite(string _spriteAtlasPath,string _spriteName)
{
//从缓存中查找图集
Sprite _sprite = FindSpriteFormBuffer(_spriteAtlasPath, _spriteName);
if(_sprite == null)
{
Debug.LogError("查找的图集为空");
Object[] _atlas = Resources.LoadAll(_spriteAtlasPath);//加载图集
m_pAtlasDic.Add(_spriteAtlasPath, _atlas);//将加载的图集存到字典中(路径对应图片)
_sprite = SpriteFormAtlas(_atlas, _spriteName);//从图集中找到图片
}
return _sprite;
}
//从图集中找出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];
}
}
}
return null;
}
//从缓存中查找图集并找出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;
}
//删除图集缓存
public void DeleteAtlas(string _spriteAtlasPath)
{
if(m_pAtlasDic.ContainsKey(_spriteAtlasPath))
{
m_pAtlasDic.Remove(_spriteAtlasPath);
}
}
}
接下来是如何使用:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class createTexture : PPTextureManager
{
private Image image;
private PPTextureManager ppTextureManage;
public GameObject obj;
// Use this for initialization
void Start ()
{
obj = transform.Find("Image").gameObject;
Sprite _sprite = PPTextureManager.getInstance().LoadAtlasSprite("Textures/common", "xiazai");
image = obj.GetComponent<Image>();
image.sprite = _sprite;
}
}
这样就可以动态使用图集中的图片啦!!!
原文链接:https://blog.csdn.net/weixin_43899724/article/details/105143806