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

原文链接: https://blog.csdn.net/cjsen/article/details/52487706

前言

在用UGUI时,我们也需要将一个个小图打包成图集,以减小Drawcall(类似coco2d-x一样,打包成图集一次性加载以内存换取图片读取效率),UGUI打包并使用图集有两种方法:一种是使用系统自带的打包工具SpritePacker;一种是使用TexturePacker打包图片并使用;

关于第一种方法可以参见另一文章,里面有详细的解释与示例使用(文章链接:http://www.xuanyusong.com/archives/3304),这种方法限制比较多,转而用另一种熟悉的方法用TexturePacker工具打包,也是本文下面要讲解的

正文

本文所使用的是Unity3d 5.4版本,TexturePacker 4.2.3版本

1,先用TexturePacker打小图打包成我们所需要的图集,打包的格式要注意是"Unity - Texture2D sprite sheet"(有一些低版本的TP是没有这个格式的),

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

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

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

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

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
//纹理图集加载管理
public class PPTextureManage : MonoBehaviour {
	private static GameObject m_pMainObject;
	private static PPTextureManage m_pContainer = null;
	public static PPTextureManage getInstance(){
		if(m_pContainer == null){
			m_pContainer = m_pMainObject.GetComponent<PPTextureManage> ();
		}
		return m_pContainer;
	}
	private Dictionary<string, Object[]> m_pAtlasDic;//图集的集合
	void Awake(){
		initData ();
	}
	private void initData(){
		PPTextureManage.m_pMainObject = gameObject;
		m_pAtlasDic = new Dictionary<string, Object[]> ();
	}
	// Use this for initialization
	void Start () {
	}
	//加载图集上的一个精灵
	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;
	}
}

5,代码使用示例

 Sprite _sprite = PPTextureManage.getInstance().LoadAtlasSprite("common/game/CommPackAltas","小图名字");

本文转载自:https://blog.csdn.net/cjsen/article/details/52487706

猜你喜欢

转载自blog.csdn.net/Csoap2/article/details/102700391