赞
踩
开始前的声明:该案例中图集所使用图片资源均来源于网络,仅限于学习使用
关于编辑器扩展相关的知识,在前面的两篇内容中做了详细的描述,链接地址:
第一篇 :Unity编辑器扩展 UI控件篇
前两篇着重于介绍编辑器界面扩展相关控件接口的使用方式。作为系列文章的第三篇,会更偏重于引擎内编辑器扩展承担 的提升开发效率的功能模块设计
通过程序化打图集减少工作量的同时可以稳定全局的管理图集,避免随着项目膨胀手动管理产生资源上的混乱。从图集整个生命周期来说,对于图集管理通常需要下面的模块支持:
本篇文章介绍第一部分,即图集程序化打包的逻辑执行
官方文档对精灵图集的描述:
在2D
项目使用精灵和其他图形来创建其场景的视觉效果。这意味着单个项目可能包含许多纹理文件。Unity
通常会为场景中的每个纹理发出一个绘制调用。但是,在具有许多纹理的项目中,多个绘制调用会占用大量资源,并会对项目的性能产生负面影响
精灵图集 (Sprite Atlas
) 是一种将多个纹理合并为一个组合纹理的资源。Unity
可以调用此单个纹理来发出单个绘制调用而不是发出多个绘制调用,能够以较小的性能开销一次性访问压缩的纹理。此外,精灵图集 API
还可以控制如何在项目运行时加载精灵图集
图集对性能开销的正向影响:
从文档描述中可以看出,图集主要在两方面影响影响性能开销:
第一,减少绘制调用,即提升合批数量,减少Draw Call
从文档的描述可以看出,图集概念出现与渲染的绘制调用相关,衡量绘制调用通常以Draw Call数量为标准。而在Unity中UI合批策略,不同的Image
控件要执行合批必须要有相同的材质、Texture
。为了满足该条件,将一些小图合并成为大图片,就可以在渲染时,尽可能的一次性的将渲染数据提交给GPU
第二,合理的图集打包策略利于资源的压缩
在前面的性能优化文章中有提到过,某些压缩策略通常只会对规则大小的图片资源生效。如下图提示,当导入的图片资源非2倍数时,引擎会弹出对应警告信息。Unity
引擎对Texture
资源的常用的DXT
压缩处理需要满足其宽度与高度的必须为4的倍数(这是因为DXT压缩策略是以4X4的像素块为基本单位做处理)
而对于图集而言,其尺寸设定策略时基于是以2的次方为基本数值,即图集是可以执行压缩的。而资源的压缩无疑会提升资源的载入速度
图集对性能开销的负面影响:
如果图集使用不当,也可能会额外占用大量的内存,举例来说,如果当前界面只使用了某一图集中很小的一张图片,却不得已将整张图集加载到内存中。亦或者说由于打入图集的Sprite
的尺寸不合理,使得图集产生大量的空白,产生额外的性能消耗
在Unity中手动打出图集的方法,在之前的文章有描述,这里稍微做一些描述,如果想了解详细的操作过程,可以查看该文章,链接地址:
Sprite Packer:
在2020.1
或更早的版本中,Unity
提供了Sprite Packer
图集纹理的生成和使用方法。相比于其他的打图集方式,Sprite Packer
是封装性较高的方式。通常只会对相应的Sprite
预设好指定图集标签。后续图集本身的资源管理基本由引擎自设定。这样做的优势可以减少开发者的工作量,但同时也牺牲了开发者对资源管理的灵活性。而不同项目的资源利用策略的不同又很需要这样的灵活性来定制
Sprite Atlas:
通过Sprite Atlas打出图集会生成对应的序列化配置文件,并且在资源面板是可见与可编辑的,可以灵活的控制图集资源的载入与卸载,当然也可以默认使用Unity自设定的加载与删除策略
动态图集:
动态图集是相对比较高阶的打图集解决方案,由于Unity没有提供与之对应的处理方法,意味着要自己实现一套集合动态资源管理、高效的图集生成算法等等
抛弃实现难度,动态图集目前是对于某些动态UI元素(如王者荣耀英雄头像)界面少有的解决方案
在对图集的理论知识做完解释后,开启核心的程序设计阶段。后面的内容主要集中于对图集程序化过程的代码解释,主要是路径围绕编辑器内资源的遍历查询、创建删除与对图集打出参数操作方面的功能模块做设计
该图集生成工具的编辑器的界面操作逻辑不是很复杂,不过也需要维护一个简单的数据类。来记录编辑的缓存数据
除了一些常规的标识ID
字段与简单的资源索引字段。稍微需要注意的是,在于对本地文件索引后SpriteAtlas
的对象的直接保存在某些操作后造成索引丢失而出现空引用。所以这里的atlas
字段会指向本地资源的实例话数据的缓存,来避免指向丢失,影响后续的数据操作
public class AtlasData
{
public string atlasName;
public string assetPath;
/// <summary>
/// 缓存中的SpriteAtlas,不直接指向本地资源
/// </summary>
public SpriteAtlas atlas;
public List<Sprite> sprites;
//编辑器界面数据
public bool isShowDital;
}
通过遍历该文件夹下所有文件(不包括子文件下的文件),并筛选出满足条件的Sprite
文件,得到该路径文件夹下的Sprite
列表。
这部分代码的逻辑设计集中于资源路径的读取遍历,基于DirectoryInfo
得到所有的文件信息,得到文件路径并通过AssetDataBase
来加载特定的Sprite
类型文件资源
在对特定类型资源文件执行遍历时,可以优先排除数量较大的Meta
文件,减少查询数量,提升文件遍历的操作效率。Unity
中文件类型通常有资源文件、代码文件、文本文件、序列化文件、Meta
文件等,通常来说,所有在Unity
中Asset
面板中可见的文件资源都会对应一份同名的meta
文件,用来记录类似于GUID
等标识身份相关的信息或者与对应资源相关的设定数据
List<Sprite> GetFileSprites(string relativePath) { if (Directory.Exists(relativePath)) { DirectoryInfo direction = new DirectoryInfo(relativePath); FileInfo[] files = direction.GetFiles("*");//只查找本文件夹下 if (files == null) return null; List<Sprite> sprites = new List<Sprite>(); foreach (var file in files) { if(file.Name.EndsWith(".meta")) continue; var item = AssetDatabase.LoadAssetAtPath<Sprite>(relativePath + file
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。