一、简介
在Unity步入2019.4以后,新版的SpriteAtlas日趋完善,已经完全可以在商业项目中使用了。但是纵观网络平台上,许多关于SpriteAtlas的文章还停留在2018的初版时期,其中许多解释在现在看来都是过时的,甚至近期UWA问答上的一篇Q&A也是错误的结论,传送门。(笔者文章写于2020.9月)如果还按照CSDN或者UWA上的这种错误的教程来使用SpriteAtlas的话,一来有可能造成图集和资源的冗余,二来会导致享受不到新版图集带来的开发便利从而影响了效率。因此进行SpriteAtlas和AssetBundle的正确配合使用调研实在必行。
二、图集的往事今生
1.NGUI和TP时代
早在NGUI时代就已经有了图集的概念了,与UGUI先使用后制作图集的工作流程不同,NGUI是先制作图集再使用。
先制作图集再使用的时候,在反复迭代开发的过程中,图集打包容易引起冲突。同时,实现规划的图集随着需求的变更可能需要重新规划,重新规划以后,又要重新打图集,之前做好的界面又要重新修复引用,这中间的工作量,经历过的人都知道。
对于NGUI这种对迭代开发十分不友好的工作流,UGUI带来的改进可以说是广大开发者的福音。
在访问NGUI图集的图元时,我们需要先加载图集,然后再从这个图集中获取单个图元,用伪代码表示大概是这个流程:
var spriteAtlas = Resources.Load("spriteAtlasName");
var sprite = spriteAtlas:GetSprite("spriteName");
2.UGUI时代的旧SpritePacker和新SpriteAtlas
和NGUI不同,UGUI访问图集的图元不需要我们主动去加载图集,再从图集中获取图元。当我们加载图集的图元时,图集会被引擎自动加载,图集的释放也是自动完成的,不需要针对图集编写任何的业务逻辑代码,而有关图集的处理工作都是放在了资源后处理、资源分组和打包上。
简单来说,就是运行时写的那些业务逻辑不需要关心我这个图元属于哪一张图集,属于哪一个AssetBundle,直接以散图的形式去使用、去获取就可以了,比如代码可以写成下面这样:
var sprite = Resources.Load("Bag/spriteName");
UGU
Objects for Pakcing指定了图集中需要打包的图元,可以指定单独的文件,也可以指定整个文件夹。
在新的作业模式中,每一个图集都是用一个单独的SpriteAtlas管理起来,图集的格式也被定义在这个资源中,预览单张图集不用像旧版的那样需要把所有的图集都集中在一个SpritePacker的编辑器窗口中预览,而是可以实时在Inspector窗口可视化预览。旧版的图集管理方式在图集数量多的时候,查找不方便还非常卡,新版的作业方式是一种分而治之的理念,更为方便和快捷。
需要注意的,UGUI的图集,无论新旧,在构建AssetBundle的时候,同一个图集内的所有图元都要放在同一个AssetBundle中,否则,如果同一个图集的图元被分散到多个AssetBundle中,那么每一个AssetBundle都会包含一份这个图集的Copy,最终的结果就是包体冗余、内存膨胀和加载耗时等问题。
如果是看的CSDN等网络上的教程的话,多半会让你不要勾选SpriteAtlas的Include In Build选项,说是会造成图集的双份冗余。但是这种说法实际上早就过时了,这个Bug早已经在Unity2018.4.6中修复了,所以我们在使用中放心大胆地勾选Include In Build就好了,这样也可以避免使用LateBinding。
同样,如果是看了网上的教程的话,也会发现有一些在使用SpriteAtlas时遇到了白图或者不显示的情况,这种情况实际上是对UGUI新图集的工作流不熟悉导致的。经过测试,只要打包的时候勾选图集的Include In Build,然后,不需要主动对SpriteAtlas资产文件进行打包,也不需要写额外的代码,就可以正常使用了,只需要对文件下下的散图进行ab打包即可。实例代码如下:string path = "UI/Atlas/MySprite.png"
var sprite = Assets.LoadAsset(path,typeof(Sprite)); //封装好的加载接口
MyImage.image = sprite;
