Unity3D UGUI图集打包与动态使用(TexturePacker)

发布时间:2024年01月03日

?制作图集的好处:
众所周知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是没有这个格式的。具体使用方法可以浏览下面的网站TexturePacker Documentation


2、打包之后会有一个.png和一个.tpsheet,不用作其他修改,将这两个文件放在工程资源中,这时从工程看这只是一张大图,并不能算是一个图集,使用里面的小图(这时虽然可以用unity3d自带功能,手动对图片进行裁剪,但裁剪的小图大小基本是不对的)

3,接下来需要下载并导入一个Unity3d的插件,TexturePacker自己出的的一个插件(TexturePacker Importer),插件链接Unity Asset Store - The Best Assets for Game Making,下载并成功导入之后,不用写任何代码,作任何操作,插件会自己根据.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_43705303/article/details/135355220
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。