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

  • 制作图集的好处:众所周知CPU是用来处理游戏的逻辑运算的,而GPU是用来处理游戏中图像的。在GPU中,我们要绘制一个图像需要提交图片(纹理)到显存,然后再进行绘制(在这个过程中会产生一次DrawCall),也就是说我们要绘制100张图片就要产生100次DrawCall.显然这是非常消耗性能的。这是制作图集的好处就显而易见了:

  1. ①、减少性能消耗,提高处理效率

  2. ②、可以归类不同模块的图片

  3. ③、一次加载或者卸载完成多图片的处理,提高了运行效率

  • 打包图集需要的工具

我们经常听说是在NGUI中打包图集,在用UGUI时,我们也需要将一个个小图打包成图集,以减小Drawcall(类似coco2d-x一样,打包成图集一次性加载以内存换取图片读取效率),UGUI打包并使用图集有两种方法:

  1. 一种是使用系统自带的打包工具SpritePacker;
  2. 一种是使用外部插件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自带功能,手动对图片进行裁剪,但裁剪的小图大小基本是不对的)

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

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

扫描二维码关注公众号,回复: 10272569 查看本文章

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

4.下面写了一个图集纹理的管理类,去统一管理加载,是一个单例类,找个不被销毁的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;

    }
}

这样就可以动态使用图集中的图片啦!!!

发布了1 篇原创文章 · 获赞 4 · 访问量 72

猜你喜欢

转载自blog.csdn.net/weixin_43899724/article/details/105143806