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

本文介绍在Unity中使用TexturePacker和SpritePacker工具进行UI图集打包的两种方法,详细解释了如何利用TexturePacker进行图集打包,并通过Unity插件TexturePackerImporter自动裁剪大图成小图。同时,提供了使用Resources.LoadAll()方法动态加载图集和小图的代码示例,以及一个纹理图集加载管理类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

TexturePacker

在用UGUI时,我们需要将一个个小图打包成图集,然后将图集一次性加载以内存换取图片读取效率,即减小Drawcall。

UGUI打包并使用图集有两种方法:一种是使用系统自带的打包工具SpritePacker,这种方法限制比较多;一种是使用TexturePacker打包图片并使用。

  1. 先打开TexturePacker把小图打包成我们所需要的图集,打包的格式要注意是"Unity - Texture2D sprite sheet"

在这里插入图片描述

打包之后会有一个.png和一个.tpsheet,直接将这两个文件放在工程资源中即可,此时从工程看这只是一张大图,并不能算是一个图集。虽然可以用Unity自带的图片裁剪的功能,但裁剪的小图大小基本不对。
在这里插入图片描述

  1. 接下来需要下载并导入一个Unity的插件,在Asset Story搜索TexturePacker Importer并导入,不用进行任何操作,插件会自己根据.tpsheet将刚才打包好放进入工程的大图自动裁剪成小图,点开图集如下:

在这里插入图片描述
我们只需像处理单独小图一样,将图集里的小图拖进Source Image里即可。此时我们只能在编辑器里设置使用图集,还不能真正使用小图。

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

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

using UnityEngine;  
using System.Collections;  
using System.Collections.Generic;  

//纹理图集加载管理  
public class PPTextureManage : MonoBehaviour {  

    private static GameObject m_pMainObject; //挂载对象
    private Dictionary<string, Object[]> m_pAtlasDic; //图集的集合,Dictionary<[key], [value]>,方便处理 

    private static PPTextureManage m_pContainer = null; //单例
    public static PPTextureManage getInstance(){  
        if(m_pContainer == null){  
            m_pContainer = m_pMainObject.GetComponent<PPTextureManage> ();  
        }  
        return m_pContainer;  
    }  

    void Awake (){  
        initData ();  
    }
    void Start () {  
    }    

    private void initData(){  //一些初始化操作
        PPTextureManage.m_pMainObject = gameObject;  
        m_pAtlasDic = new Dictionary<string, Object[]> ();  
    }  

    //删除图集缓存  
    public void DeleteAtlas(string _spriteAtlasPath){  //字典的键为路径
        if (m_pAtlasDic.ContainsKey (_spriteAtlasPath)) {  //ContainsKey为Dictionary的方法,判断是否存在指定键名,不可以使用get来判断是否存在某个键,因为当键存在,值不存在,也返回null
            m_pAtlasDic.Remove (_spriteAtlasPath);  //Remove为Dictionary方法,移除键值
        }  
    } 

    //加载图集上的一个精灵  
    public Sprite LoadAtlasSprite(string _spriteAtlasPath,string _spriteName){  //第一个参数为图集路径,第二个参数为精灵图名
        Sprite _sprite = FindSpriteFormBuffer (_spriteAtlasPath,_spriteName);  //FindSpriteFormBuffer,先从缓存中查找sprite

        if (_sprite == null) {  //当_sprite找不到,说明m_pAtlasDic的Object[]为空,还未缓存Object[]
            Object[] _atlas = Resources.LoadAll (_spriteAtlasPath);  
            m_pAtlasDic.Add (_spriteAtlasPath,_atlas);  
            _sprite = SpriteFormAtlas (_atlas,_spriteName);  //SpriteFormAtlas,直接从图集本身查找
        }  
        return _sprite;  
    }  

    //从缓存中查找图集,并找出sprite  
    private Sprite FindSpriteFormBuffer(string _spriteAtlasPath,string _spriteName){  //第一个参数为图集路径,第二个参数为精灵图名
        if (m_pAtlasDic.ContainsKey (_spriteAtlasPath)) {  //如果键名存在
            Object[] _atlas = m_pAtlasDic[_spriteAtlasPath]; //把m_pAtlasDic值保存起来,即图集数组 
            Sprite _sprite = SpriteFormAtlas(_atlas,_spriteName);  //在m_pAtlasDic值中寻找
            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
        return null;  
    }  
} 
  1. 代码使用示例
Sprite _sprite = PPTextureManage.getInstance().LoadAtlasSprite("common/game/CommPackAltas","小图名字");  

原文:https://blog.csdn.net/weixin_39706943/article/details/80522010

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值