Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【Unity游戏开发】SpriteAtlas与AssetBundle最佳食用方案

【Unity游戏开发】SpriteAtlas与AssetBundle最佳食用方案

作者头像
马三小伙儿
修改于 2021-04-29 02:48:45
修改于 2021-04-29 02:48:45
9.2K50
代码可运行
举报
运行总次数:0
代码可运行

一、简介

  在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图集的图元时,我们需要先加载图集,然后再从这个图集中获取单个图元,用伪代码表示大概是这个流程:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var spriteAtlas = Resources.Load("spriteAtlasName");

var sprite = spriteAtlas:GetSprite("spriteName");

2.UGUI时代的旧SpritePacker和新SpriteAtlas

  和NGUI不同,UGUI访问图集的图元不需要我们主动去加载图集,再从图集中获取图元。当我们加载图集的图元时,图集会被引擎自动加载,图集的释放也是自动完成的,不需要针对图集编写任何的业务逻辑代码,而有关图集的处理工作都是放在了资源后处理、资源分组和打包上。

  简单来说,就是运行时写的那些业务逻辑不需要关心我这个图元属于哪一张图集,属于哪一个AssetBundle,直接以散图的形式去使用、去获取就可以了,比如代码可以写成下面这样:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var sprite = Resources.Load("Bag/spriteName");

  UGUI图集的先使用后制作主要有两种作业模式,也就是旧的SpritePacker和新的SpriteAtlas模式:

1.旧的SpritePacker模式,给Sprite设置PackingTag,Tag相同的会被分配到同一个图集中,如下图所示

2.新版的SpriteAtlas相比之前的SpritePacker做了更多的优化,比如可以实时查看图集的大小,图集里面元素的排列布局,并且增加了LateBinding等特性

  我们可以通过Asset/Create/Sprite Atlas去创建一个图集,图集创建以后可以通过拖拽的方式去选择要打包的对象,如下图所示:

  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打包即可。实例代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
string path = "UI/Atlas/MySprite.png"

var sprite = Assets.LoadAsset(path,typeof(Sprite)); //封装好的加载接口

MyImage.image = sprite;

三、实践工程

  为了佐证上面的一些结论,这里特意配置了一份教练工程。

  首先有一个引用了图集中图元的UIPrefab,如下图所示,它上面有三个Image,右边的两张Image分别引用了同一个图集中的图元,我们用它来验证图元是否合批,左边的Image是引用了另外一个图集中的图元,我们用它来对比验证DrawCall:

  然后这里面有三分SpriteAtlas文件,它们都勾选了Include In Build 但是不参与打包。这三个图集分别管理这Sprites目录下的每个子目录中的散图文件,这些散图文件时需要参与打包的(AssetBundle)。

  然后我们进行打ab操作,打出ab以后我们用AssetStudio去验证ab包的内容,看看它有没有冗余情况出现。首先看一下打出来的UIPrefab的ab文件,prefabs_uiroot.bundle,可以看到尽管UIPrefab引用了图集里面的图元,并且图集勾选了Include In Build,但是并没有UIPrefab的ab里面并没有冗余,Unity的确是修复好了这个bug:

  然后再来看一下图集的ab包,因为没有对.spriteatlas文件特意的包,所以打包的实际上按目录划分的散图文件,shared_ui_sprites_game.bundle,可以看到里面只有Texture和Sprite,也没有多余的冗余文件出来:

  但是,如果我们故意指定对.spritealtas文件也打包,特意指定一下,然后我们再看spriteatlas资源文件打出来的ab,atlas_game.bundle,可以发现里面有个合并好的512x512的图集,这个就造成了的冗余,因为散图目录下已经有一份资源文件了:

  然后我们再看下,只设置了图集,但是不特意针对图集进行导出打包的情况下,UI使用图集内的图元,是否还可以正常的合批,DrawCall是否正常。

  通过上面的一些信息,我们可以看到Unity进行了合批操作,DrawCall为3也是正常的。在FrameDebugger里面也可以看到引用了同一图集内的两张图元的Image,也是在一个Batch里面去绘制的。

四、总结

  实际上,通过上面的一系列测试,我们可以得出以下结论,新版的SpriteAtlas可以看做是对旧版的SpritePacker的升级,我们在使用的时候仍然是不需要关注图集这个东西的,这里的SpriteAtlas可以看做仅仅是用来作为一种对散图的归纳与整理。当我们加载图集的图元时,图集会被引擎自动加载,图集的释放也是自动完成的,不需要针对图集编写任何的业务逻辑代码,而有关图集的处理工作都是放在了资源后处理、资源分组和打包上。简单来说,就是运行时写的那些业务逻辑不需要关心我这个图元属于哪一张图集,属于哪一个AssetBundle,直接以散图的形式去使用、去获取就可以了。

简单来说遵循以下几点就不会有错了:

  • 工作过程中(拼接UI等)放心大胆地以散图的方式去引用UI/Atlas/XXX下的各种图片即可
  • SpriteAltas文件需要勾选Include In Build,但是不要特意打包,会造成冗余和包体膨胀
  • 代码中动态加载Sprite的地方,直接使用散图的资源路径去加载就可以了,比如:var sprite = Assets.LoadAsset<Sprite>(path);
  • 平时工作的机器上SpritePacker的Mode可以设置为Disable,这样可以提高效率(开启的话每次Run之前,图集会打包,资源多了以后会卡)。但是在打包机上一定要把Mode设置为Enable for build或者Always enable,这样图元才能被正确地合批
  • 同一个图集内的所有图元打包时都要放在同一个AssetBundle中

作者:马三小伙儿

出处:https://cloud.tencent.com/developer/article/1765934

请尊重别人的劳动成果,让分享成为一种美德,欢迎转载。另外,文章在表述和代码方面如有不妥之处,欢迎批评指正。留下你的脚印,欢迎评论!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-12-28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
5 条评论
热度
最新
我不是很明白,为什么图集中的图片还要参与打包. 我的理解是, 要在UI上定位吗? 如果我代码手挫, 就想加载一些现在项目中还没有的图片. 比如节日或者活动的图片. 那如何使用? 我只是想把图片资源打成AB包, 不想重新发布. 感觉好麻烦.
我不是很明白,为什么图集中的图片还要参与打包. 我的理解是, 要在UI上定位吗? 如果我代码手挫, 就想加载一些现在项目中还没有的图片. 比如节日或者活动的图片. 那如何使用? 我只是想把图片资源打成AB包, 不想重新发布. 感觉好麻烦.
回复回复点赞举报
感谢分享。不过这边测试发现了些问题。使用 2022.3.8f1c1 进行了测试,如果图集文件设置了IncludeInBuild,并且不标记ab,只标记散图和预制为ab,打包后,图集文件实际打入了apk/exe构建包中(可以在BuildReport中看到),运行时也是从这里加载过来的,而不是ab包(最简单的,删除了ab包中对应的散图资源,程序依然正常运行显示图片)。
感谢分享。不过这边测试发现了些问题。使用 2022.3.8f1c1 进行了测试,如果图集文件设置了IncludeInBuild,并且不标记ab,只标记散图和预制为ab,打包后,图集文件实际打入了apk/exe构建包中(可以在BuildReport中看到),运行时也是从这里加载过来的,而不是ab包(最简单的,删除了ab包中对应的散图资源,程序依然正常运行显示图片)。
11点赞举报
我这用2021.3.25f1c1 测试的时候挺正常的, 和作者说的一致, 删除了ab包中对应的散图资源也会报错. 用的是addressable, 图集不打包, 图集版本选的是v1, 不知道别的情况是不是也一样. 只打包散图. 出的windows包, 从StreamingAssets加载出来可以自动合批, 删了也会报错, 我甚至试了把散图打成散的bundle资源, 打包运行还是一个drawcall, 删了其中一个, 同一个图集里其他的图都白的. 图片资源总的文件大小大了20%, 可能有点冗余但是不多, 有空再用AssetStudio看一下, 但是合批和加载都没问题. 还挺神奇的...
我这用2021.3.25f1c1 测试的时候挺正常的, 和作者说的一致, 删除了ab包中对应的散图资源也会报错. 用的是addressable, 图集不打包, 图集版本选的是v1, 不知道别的情况是不是也一样. 只打包散图. 出的windows包, 从StreamingAssets加载出来可以自动合批, 删了也会报错, 我甚至试了把散图打成散的bundle资源, 打包运行还是一个drawcall, 删了其中一个, 同一个图集里其他的图都白的. 图片资源总的文件大小大了20%, 可能有点冗余但是不多, 有空再用AssetStudio看一下, 但是合批和加载都没问题. 还挺神奇的...
回复回复点赞举报
如果是后期热更新资源,没有重新打包项目,这种情况,图集要单独打包和使用LateBinding吗?
如果是后期热更新资源,没有重新打包项目,这种情况,图集要单独打包和使用LateBinding吗?
回复回复点赞举报
大佬写的太好了,百度了一堆都是过期的。大佬这篇简单明了
大佬写的太好了,百度了一堆都是过期的。大佬这篇简单明了
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
Unity SpriteAtlas 使用FAQ
这两天详细的看了下U3D的新图集系统 SpriteAtlas ,目前为止觉得这个新系统用起来问题不大。但是在理解上有一些问题,我会在这里做一些记录。 在操作上,这个没什么问题。有问题的是SpriteAtlasManager这块,需要去理解一下调用机制。
keyle
2024/11/01
1970
Unity SpriteAtlas 使用FAQ
如何快速优化手游性能问题?从UGUI优化说起
作者Feefi,加入腾讯多年,目前主要从事Unity项目UI开发及优化相关工作,曾获得国际软件设计大赛“成都创业金钥匙”奖。
WeTest质量开放平台团队
2018/10/29
1.6K0
【Unity面试篇】Unity 面试题总结甄选 |Unity性能优化 | ❤️持续更新❤️
Unity中,CPU准备好需要绘制的元素,对底层图形程序接口进行调用的过程,每次引擎准备数据并通知GPU的过程称为一次Draw Call。DrawCall越高对显卡的消耗就越大。 降低DrawCall的方法:
呆呆敲代码的小Y
2023/07/24
2.9K0
【Unity面试篇】Unity 面试题总结甄选 |Unity性能优化 | ❤️持续更新❤️
【Unity游戏开发】AssetBundle杂记--AssetBundle的二三事
  马三在公司大部分时间做的都是游戏业务逻辑和编辑器工具等相关工作,因此对Unity AssetBundle这块的知识点并不是很熟悉,自己也是有打算想了解并熟悉一下AssetBundle,掌握一下Unity资源管理方面的知识,因此有了这篇博客。
马三小伙儿
2018/09/12
3.5K0
【Unity游戏开发】AssetBundle杂记--AssetBundle的二三事
Unity Sprite Altas「建议收藏」
Sprite Atlas(精灵图集) Sprite Atlas 针对现有的图集打包系统Sprite Packer在性能和易用性上的不足,进行了全面改善。除此之外,相比Sprite Packer,Sprite Atlas将对精灵更多的控制权交还给用户。由用户来掌控图集的打包过程以及加载时机,更加利于对系统性能的控制。 Sprite Atlas的主要有以下三个功能: 1.创建、编辑图集以及设定图集参数
全栈程序员站长
2022/11/01
2.1K0
Unity Sprite Altas「建议收藏」
Unity网络交互☀️AssetBundle一、:用途、创建、解读、接口
为减少网页游戏的下载时间,通常将游戏进行拆分,玩家边玩边下载,手机端游戏同样适用。
星河造梦坊官方
2024/08/15
3770
Unity网络交互☀️AssetBundle一、:用途、创建、解读、接口
Unity AssetBundle
#AssetBundle作用原理 把资源导出成一种叫做AssetBundle的文件,然后打包后可以在Unity程序运行的时候再加载回来用。 AssetBundle是采取某一种压缩方式压缩成的资源文件。节省存储空间,控制游戏包的大小,实现游戏的热更新。
全栈程序员站长
2022/09/12
1.3K0
Unity AssetBundle
AssetBundle使用模式
原文链接:https://www.jianshu.com/p/22a6876d39b5
bering
2019/12/03
2.3K0
Golang语言情怀--第118期 全栈小游戏开发:第9节:精灵帧资源(SpriteFrame)
Cocos Creator 的 SpriteFrame 是 UI 渲染基础图形的容器。其本身管理图像的裁剪和九宫格信息,默认持有一个与其同级的 Texture2D 资源引用。
李海彬
2023/11/22
4190
Golang语言情怀--第118期 全栈小游戏开发:第9节:精灵帧资源(SpriteFrame)
AssetBundle详解
AssetBundle是将资源使用Unity提供的一种用于存储资源的压缩格式打包后的集合,它可以存储任何一种Unity可以识别的资源,如模型,纹理图,音频,场景等资源。也可以加载开发者自定义的二进制文件。他们的文件类型是.assetbundle/.unity3d,他们先前被设计好,很容易就下载到我们的游戏或者场景当中。
全栈程序员站长
2022/09/13
2.1K0
AssetBundle详解
Cocos游戏开发入门最佳实践
因为公司的业务需求,近期学习了CocosCreator这款游戏引擎的开发,也基于此上线了一款游戏,因此写这系列文章记录一下我从入门到项目发布的学习过程。
异名
2020/06/09
1.3K0
连“捉阔”是什么都不知道就不要混了!如何优化看这里!
在游戏开发中,DrawCall 作为一个非常重要的性能指标,直接影响游戏的整体性能表现。
张晓衡
2020/07/09
2.3K0
连“捉阔”是什么都不知道就不要混了!如何优化看这里!
AssetBundle相关
====>AssetBundle打包:设置好AssetBundle包名后,利用BuildPipeline.BuildAssetBundles (“Path”);进行打包。
全栈程序员站长
2022/09/07
3580
AssetBundle相关
AssetBundle 详解
在 Assets 文件夹中创建一个名为 Editor 的文件夹,并将包含以下内容的脚本放在该文件夹中:
全栈程序员站长
2022/09/07
2.5K0
Unity不仅有AssetBundle,其实还有个SceneBundle,你了解吗?
本号已有原创文章280+篇,以软件工程为纲,DevOps为基,洞察研发效能全貌,涵盖从需求管理、应用/游戏开发、软件测试、发布部署到运营监控的完整流程。无论您是项目经理、产品经理、开发人员、测试人员,还是运维人员,在这里您都可以有所收获,同时深入理解其他角色的工作内容,共同助力DevOps的成功落地。欢迎关注,有任何问题可发送私信~
DevOps持续交付
2024/03/19
3390
Unity不仅有AssetBundle,其实还有个SceneBundle,你了解吗?
[学习笔记]unity3d-UGUI
简介 Unity 图形用户界面(unity Graphical User Interface) Unity4.6版本之后引入的界面显示系统 Unity公司自己研发的一套界面显示系统 UGUI和OnGUI、NGUI的区别 uGUI的Canavas有世界坐标和屏幕坐标 uGUI的Image可以使用material UGUI通过Mask来裁剪,而NGUI通过Panel的Clip NGUI的渲染前后顺序是通过Widget的Depth,而UGUI渲染顺序根据Hierarchy的顺序,越下面渲染在顶层。 UGUI不需要
六月丶
2022/12/26
3.2K0
[学习笔记]unity3d-UGUI
【Unity游戏开发】浅谈 NGUI 中的 UIRoot、UIPanel、UICamera 组件
马三最近换到了一家新的公司撸码,新的公司 UI 部分采用的是 NGUI 插件,而之前的公司用的一直是 Unity 自带的 UGUI,因此马三利用业余时间学习了一下 NGUI 插件的使用,并把知识点记录成博客与大家分享。
马三小伙儿
2018/09/12
1.7K0
【Unity游戏开发】浅谈 NGUI 中的 UIRoot、UIPanel、UICamera 组件
【Unity游戏开发】UGUI不规则区域点击的实现
  马三从上一家公司离职了,最近一直在出去面试,忙得很,所以这一篇博客拖到现在才写出来。马三在上家公司工作的时候,曾处理了一个UGUI不规则区域点击的问题,制作过程中也有一些收获和需要注意坑,因此记录成博客与大家分享。众所周知在UGUI中,响应点击通常是依附在一张图片上的,而图片不管美术怎么给你切,导进Unity之后都是一个矩形,如果要做其他形状,最多只能旋转一下,或者自己做一些处理。而为了美术效果,很多时候我们不得不需要特定形状的UI,并且让它们实现精准的响应点击。例如下图就是一个不规则的点击区域。
马三小伙儿
2018/09/12
3.7K0
【Unity游戏开发】UGUI不规则区域点击的实现
Unity 热更新技术 | (二) AssetBundle - 完整系列教程学习
AssetBundle(简称AB包)是一个资源压缩包,可以包含模型、贴图、音频、预制体等。如在网络游戏中需要在运行时加载资源,而AssetBundle可以将资源构建成 AssetBundle 文件。
呆呆敲代码的小Y
2023/03/16
3.5K0
Unity 热更新技术 | (二) AssetBundle - 完整系列教程学习
零基础入门 4: 窗口介绍(完)
上一篇将Unity里几个比较重要的窗口先进行了讲解,以及如何自定义窗口布局,不知道大家都消化的怎么样,今天这篇窗口介绍,将把剩余window的窗口一一进行介绍。
韩东吉
2018/10/19
1.7K0
零基础入门 4: 窗口介绍(完)
推荐阅读
相关推荐
Unity SpriteAtlas 使用FAQ
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验