前言

图集打包的好处都有啥?不管你是新手还是大神,要是项目中ui图片很多,特别是小图很多,需要运行时动态加载或切换Image中的sprite的时候,基本上都会选择打包成图集这种解决方案。

图集的好处有很多,我就说一下主要的两点,其它的大家可以问度娘:

  • 减少DrawCall,虽然新版Unity没有DrawCall显示了,但也引入了Batches和SetPass calls这两个数值,实际上都是指图片渲染的次数(这样说可能有点不严谨,但代表这个意思)。每张单独的图片占用一次渲染,假如10张小图,就10次渲染了,但如果这10张小图打到一个图集里面,那么系统只需渲染1次即可,大大减少系统负担
  • 减轻IO负担,假如你每次加载图片的时候还是用Load()之类的通过操作IO读写的方式来加载的话,那么每次加载图片都需要进行一次IO读写,而使用图集之后只需一次读取图集到内存中,那么每次加载图片就只需从内存中取出,大大减轻系统负担,当然,这是舍弃内存保速度的解决方案。

图集打包工具我推荐大家用TexturePacker,虽说用unity自带SpritePacker也可以,功能也差不多,但我个人认为自带的用起来并不顺手。关于TexturePacker软件的使用教程,可以查看我之前发表过的文章(请务必使用TexturePacker4.8.1版的教程),链接:http://www.tinkingli.com/?p=302

代码解读

代码十分简单,主要就两个.cs文件AtlasPackerEditor.cs和SpriteData.cs。

SpriteData.cs

这个类是继承自MonoBehaviour的,大家只需要获取到这个组件的引用,调用GetSprite()方法即可

[ExecuteInEditMode()]
public class SpriteData : MonoBehaviour
{public Sprite[] sprites;private Dictionary<string, int> Index = new Dictionary<string, int>();private int indexS = 0;public Sprite[] SetSP{set{sprites = value;}}public Sprite GetSprite(string spName){if (Index.Count == 0){for (int i = 0; i < sprites.Length; i++){Index.Add(sprites[i].name, i);}}if (Index.TryGetValue(spName, out indexS)){return sprites[indexS];}return null;}
}

而另一个类是Editor类,需要放在Editor文件下

    /// <summary>/// 图集图片的路径/// </summary>public static string AtlasPath = "Assets/codeandweb.com/Example/SpriteSheet";/// <summary>/// 打包后预制体存放路径/// </summary>public static string UISharePath = "Assets/codeandweb.com/Example/";

使用前请修改AtlasPath和UISharePath两个路径为自定义路径

    [MenuItem("渐渐/打包所有图集")]public static void PackAtlas(){string[] _patterns = new string[] { "*.png" };string multiTag = "_multi_";Dictionary<string, List<string>> _allFilePaths = new Dictionary<string, List<string>>();string _tempName = String.Empty;foreach (var item in _patterns){string[] _temp = Directory.GetFiles(AtlasPath, item, SearchOption.AllDirectories);foreach (string path in _temp){System.IO.FileInfo _fi = new System.IO.FileInfo(path);_tempName = _fi.Name.Replace(_fi.Extension, "").ToLower();if (!_tempName.Contains(multiTag)){_tempName = "atl_" + _tempName;}else{_tempName = "atl_"+ _tempName.Split(multiTag)[0];}if (!_allFilePaths.ContainsKey(_tempName)){_allFilePaths.Add(_tempName, new List<string>());}_allFilePaths[_tempName].Add(path);}}foreach (var item in _allFilePaths){CreateAtlasPrefab(item.Key, item.Value.ToArray());}}

此处遍历AtlasPath文件夹下的所有.png图片(可以根据项目需要添加或修改为.jpg等),然后用于创建图集,大家应该发现,此处用到一个关键词“_multi_”,这个适用于多图片图集,后面会介绍用法

    //创建图集预设public static void CreateAtlasPrefab(string atlasName, string[] atlPath){List<Sprite> _texs = new List<Sprite>();foreach (string path in atlPath){_texs.AddRange(AssetDatabase.LoadAllAssetsAtPath(path).OfType<Sprite>().ToArray());}if (null != _texs){GameObject _go = new GameObject();_go.name = atlasName;SpriteData _spData = _go.AddComponent<SpriteData>();_spData.SetSP = _texs.ToArray();string path1 = UISharePath + atlasName + ".prefab";GameObject temp = PrefabUtility.CreatePrefab(path1, _go);#region 添加ab标记//此处自动添加ab标记//如果加载方式是Resources.load()等不需要ab标记的可以把此处注释掉AssetImporter importer = AssetImporter.GetAtPath(path1);if (importer == null || temp == null){Debug.LogError("error: " + path1);return;}importer.assetBundleName = "ui-share.unity3d";#endregionGameObject.DestroyImmediate(_go);EditorUtility.SetDirty(temp);AssetDatabase.SaveAssets();}Resources.UnloadUnusedAssets();AssetDatabase.Refresh();}

此处我添加了一个ab标记,因为在我项目中所有用这个方法打包的都是UI的Share包,如果不了解或不需要用到AssetBundle的朋友,请务必把这个注释掉

打包图集预设


此处是放置图集文件的地方,然后把AtlasPackerEditor.cs里的AtlasPath路径设置为此处。

然后设置UISharePath为图集预制体存放路径

点击渐渐->打包所有图集

即可看到图集已经自动打包好了

多图片图集使用方法:假如你们UI的图集非常大,2048*2048的图片都放不下(unity限制2048),需要两张或以上的图集图片,这时候图片的命名只需为:UI_multi_1,UI_multi_2,

UI_multi_3以此类推,最后打包只会出现一个预制体,这样加载的时候就像单张图集那样加载了。

动态加载

1、首先,我们需要加载atl_开头的预制体,你可以把导出路径放在Resources文件夹下,这样就可以通过调用Load()来加载了,你也可以像我那种通过AssetBundle的方式来加载

2、Load出来的prefabs并不需要像一般预制体那样实例化到场景,直接GetComponent<SpriteData>()即可获得SpriteData的引用,我们保存这个引用即可

3、当需要加载其中的图片的时候调用GetSprite(spriteName)即可

此处各位可以做一个LoadHelper来保存SpriteData引用和自动加载,各位也可以根据需求改成异步加载和异步获取,此处不作介绍

public static class LoadSpriteHelper
{//所有图集名public const string Atl_UI = "UI";public const string Atl_Scene = "Scene";public const string Atl_Role = "Role";/// <summary>/// SpriteData缓存/// </summary>private static Dictionary<string, SpriteData> spriteDates = new Dictionary<string, SpriteData>();/// <summary>/// 获取图片(自动加载缺失的图集)/// </summary>/// <param name="atlName"></param>/// <param name="spriteName"></param>/// <returns></returns>public static Sprite LoadSprite(string atlName, string spriteName){if (!spriteDates.ContainsKey(atlName)){GameObject atl = null;//todo 此处加载atl_开头的预制体spriteDates.Add(atlName, atl.GetComponent<SpriteData>());}return spriteDates[atlName].GetSprite(spriteName);}
}

下载:

GitHub(国外):

ET模组仓库: https://github.com/egametang/ET-Modules.git

本人工具仓库:https://github.com/HealthyChina/HealthyResource.git

Gitee(国内):

本人工具仓库:https://gitee.com/healthyZ/HealthyResource.git

UGUI中动态加载图集中的图片(转)相关推荐

  1. uni中动态加载class_SpringBoot中使用LoadTimeWeaving技术实现AOP功能

    1. 关于LoadTimeWeaving 1.1 LTW与不同的切面织入时机 AOP--面向切面编程,通过为目标类织入切面的方式,实现对目标类功能的增强.按切面被织如到目标类中的时间划分,主要有以下几 ...

  2. 在.Net framework中动态加载Assembly的loadFromRemoteSources配置

    简介 在插件类型的应用开发中,我们可能会在程序中动态加载一个assembly文件,创建其中的类对象并使用. 这时,就涉及到了CAS(code access security)和信任沙盒. 一般,我们的 ...

  3. 在VC中动态加载ODBC的方法

    在VC中动态加载ODBC的方法     在使用VC.VB.Delphi等高级语言编写数据库应用程序时,往往需要用户自己在控制面板中配置ODBC数据源.对于一般用户而言,配置ODBC数据源可能是一件比较 ...

  4. Node.js项目中动态加载环境变量配置

    NODE_MODULES:项目中动态加载环境变量配置 开始 在平时的 Node.js 项目开发中,我们需要在项目中添加各种各样的配置:服务端口.服务地址.图片上传.数据库.Redis 等等. 通常情况 ...

  5. bpl文件java,在LoadLibrary中动态加载BPL失败

    我想在Delphi 10 Seattle(Update 1)或Delphi 10.1 Berlin项目(Enterprise版本)中动态加载BPL模块 . 但LoadPackage函数失败并显示消息( ...

  6. Java中动态加载字节码的方法 (持续补充)

    文章目录 Java中动态加载字节码的方法 1.利用 URLClassLoader 加载远程class文件 2.利用 ClassLoader#defineClass 直接加载字节码 2.1 类加载 - ...

  7. python requests 动态加载_Python获取网页中动态加载的数据

    Python获取网页中动态加载的数据 0.XHR 是什么? XHR是 XMLHttpRequest 对象.既Ajax功能实现所依赖的对象,在JQuery中的Ajax是对 XHR的封装. 1.查看异步加 ...

  8. Android中WebView加载sdcard中的html时提示:ERR_FILE_NOT_FOUND和ERR_ACCESS_DENIED

    场景 Android中WebView加载sdcard中的html显示: Android中WebView加载sdcard中的html显示_BADAO_LIUMANG_QIZHI的博客-CSDN博客 在实 ...

  9. C#中动态加载和卸载DLL

    在C++中加载和卸载DLL是一件很容易的事,LoadLibrary和FreeLibrary让你能够轻易的在程序中加载DLL,然后在任何地方卸载.在C#中我们也能使用Assembly.LoadFile实 ...

最新文章

  1. 有n个学生选修了c语言程序设计这门课程,C语言程序设计报告学生选修课系统(18页)-原创力文档...
  2. spring系统学习:day4--Spring配置: 集合类型属性的注入
  3. JAVA-初步认识-第十一章-异常-概述
  4. ASP.NET 访问共享文件夹
  5. jar打包 剔除第三方依赖以及它的依赖_maven打包成第三方jar包且把pom依赖包打入进来的方法...
  6. linux内核源码代码量,Linux内核源代码数量已经超过1000万行
  7. 计算机单词大全及缩写,计算机英文单词和缩写
  8. 控制工程基础Chapter1 Introduction to Control Systems
  9. VirtualBox创建虚拟电脑、执行Genymotion模拟器报错
  10. Linux下的SYN flood***
  11. tomcat以debug模式启动
  12. HTML(五)列表,区块,布局,表单和输入
  13. 问题 G: [入门OJ]差(NHOI2015xj6)
  14. windows11 笔记本开启热点就断网
  15. 油猴安装、编写及添加脚本 笔记
  16. windows管理右键新建的方法
  17. uni-app 中微信小程序使用高德地图等第三方 SDK的方法
  18. 【综述篇】(1)无人驾驶/机器人规划方向综述
  19. LSI阵列卡查看SSD寿命
  20. ubuntu双网卡共享上网

热门文章

  1. 隐藏win32控制台程序的窗口
  2. 【UE4 C++】读取灰度图/RGB图中的像素值生成自定义形状的模型分布
  3. Ubuntu:apt 配置阿里源
  4. 小睿睿的伤害(树上启发式合并)
  5. Win7上通过DckerToolbox部署OnlyOffice
  6. 安装saltstack遇到缺包问题!自己遇到的错!若有雷同请海涵
  7. mysql5.7和mysql8.0区别
  8. jsp连接oracle数据库
  9. [Errno 13] Permission denied:解决办法
  10. MATLAB图像识别手写数字(第一篇:准备数据)