UGUI的图集处理方式-SpriteAtlas的前世今生
最糟糕的是人们在生活中经常受到错误志向的阻碍而不自知,真到摆脱了那些阻碍时才能明白过来。 —— 歌德
说到UGUI的图集初学者可能觉得没什么难度,包括我刚开始接触的时候也是,甚至你在开发的时候只需要把图片导入到项目中,拖拖拽拽就能做出能用的东西来。因为UGUI刚出的时候就打出了“Unity会自动帮你维护图集”的旗号。可现实真的是这样的吗?要解释这个问题就需要从Unity4.6说起了,那我们来捋一下!
Sprite Packer
散图的加载问题
这功能是从Unity4.6版本随着UGUI的问世一起发布的,我们在做开发的时候只需要把图片导入工程,设置一下,然后在通过tag标签Unity就会自动打成图集。但是,这种方法有个问题,就是我们在运行时无法通过代码取出某张图集中的一张小图。
所以后来开发者们做了一套prefab引用sprite的解决方案,做法就是:建一个空prefab挂一个自定义脚本,脚本里有一个sprite数组,我们在编辑时把要打的图集中的sprite添加到这个sprite数组中,然后在把prefab打成bundle,这样这个bundle中的脚本就会有atlas中的Sprite的引用,我们在脚本里写一个GetSprite方法即可。这样我们在运行时加载完bundle后就可以通过脚本取出atlas里的sprite。
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
public List<Sprite> sprites;
public Sprite GetSprite(string spriteName)
{
return sprites.Find(s => s.name.Equals(spriteName));
}
}
但是,讲真,就这么个函数Unity提供一个API很难嘛!这个问题导致从Unity4.6到Unity2017.1每次做图集动态加载的时候都要用上面的方法搞一遍。当然要是仅仅是这点工作量也就忍了,重要的是这么做还会影响到打包、依赖的管理。打包依赖又是个Unity的大坑。。。一个坑跳到了另一个更深的坑。。。当然也是有解决办法的,打包依赖问题我们以后再专门讲,这里就不多说了。
图集的拼接算法问题
SpritePacker的TightPackerPolicy(紧凑),根本就不能用!SpritePacker打图集时有两个选项:默认、紧凑,然而使用过你会知道其实这个“紧凑”选项是不能用的!!打出来的图会串,你用一张Image指定了一张Sprite A,运行时你会发现如果用“紧凑”打出来的图集会把A的范围算错,表现就是显示的图片不是A,可能只包括A的一部分,其他部分会显示别的图片,其实就是取A这张图片的时候位置没算对!!!最终你会发现也只能使用”默认”方式打图集了。如果想优化图集的空间利用率,只有一个办法就是自己写打图集的排列算法,当然Unity也提供了这个接口!
Sprite Atlas
延迟绑定
SpriteAtlas是2017.1版本以后更新的一个新功能,它可以把图片“手动”打成一张图集。如果你觉得这是Unity的一个新功能或者一个强化图集的功能那你就错了,如果仅仅是打张图集也没必要单独搞这么个玩意儿,其实这也是Unity在“还SpritePacker的帐”,当然我们上面也讲到了,可以肯定的一点是SpritePacker在商业项目中:是能用的!但是不可避免的你会为了填补SpritePacker的一些坑。
SpritePacker时代“图集”我们是看不到的,因为设计者的初衷是想让开发者完全不用考虑图集的事。但是,这跟游戏开发时的动态加载图集时矛盾的!我们要动态加载就必须要知道atlas名字和sprite名,这样才能在运行时动态的找到一张sprite!所以U3D程序员必须要清楚的知道你当前界面用的是哪atlas的哪个sprite。但是按照SpritePacker的做法他的初衷应该是想把图集干掉(干掉的意思让开发者不用关心),只需要考虑sprite即可,但是这是行不通的!
SpriteAtlas其实就是为了解决上面说的问题而发布的功能。通过它我们可以将atlas和UIprefab“解耦”。同时,在Unity编辑器状态下我们仍然可以利用未打成SpriteAtlas的Sprite进行开发。等开发完成我们再发布成SpriteAtlas。Unity提供了所谓“延迟绑定”(late bind)的技术来让我们实现这个功能。具体做法如下:
在Unity2017.1之后,UI prefab的Bundle在被加载的时候会有一个回调函数被调用:SpriteAtlasManager.atlasRequested,这个委托的定义是这样的:void RequestLateBindingAtlas(string atlasName, System.Action output);
(代码不严格,当成伪码看就行))
SpriteAtlasManager.atlasRequested += (atlasName, output) => {
string path;//省略,atlas bundle加载路径
AssetBundle bundle;//省略,加载atlas的asset bundle
var atlas = bundle.LoadAsset<SpriteAtlas>(path + "/" + atlasName);
output(atlas);
}
我们需要在运行时把atlas绑定到当前的prefab中,这个绑定是通过第一个参数"atlasName"关联的。如果prefab中引用了多张atlas他会被调用多次,每次都会把atlasName传过来,由“用户”决定加载哪张atlas。最后调用output(atlas)把图集传给prefab。
延迟绑定的缺陷(bug)
Include in Build选项
根据实测,这个选项的含义是:选,打包时不考虑依赖。不选,打包时考虑依赖。
举例:
文件夹"A"存放着要使用的图片,SpriteAtlas文件“A_Atlas”为文件A下所有图片打成的图集,Prefab文件“A_Prefab”引用了A下的图片。
此时,
如果选择Include in Build,那么打包的时A_Prefab打出来的bundle文件会包含A下面的图片,A_Atlas打出来的bundle也会包含A下面的图片,也就是说此时会打包双份资源。这是我们不想看到的。
如果不选Include in Build,只有A_Atlas打出来的bundle会包含A下的图片,而A_Prefab不会包含A下的图片。这样资源只打包了一份,是我们想要的结果。
但是,
有个地方需要注意就是,如果A_Atlas第一次勾选了Include in Build,打包后A_Prefab和A_Atlas的bundle都会包含图片资源,但是如果此时再把A_Atlas的Include in Build的勾去掉重新打包,Unity只会把A_Atlas的bundle重打,因为Unity认为你只修改了A_Atlas文件,而A_Prefab被认为”没有更改”,所以之前打进去的图片资源依然会存在,正确的做法应该是:如果Include in Build修改了,那么打包的时候所有用到这个SpriteAtlas的prefab也要重新打包(删掉bundle文件即可)
Unity编辑器状态下运行UI全部白图(bug)
这应该是Unity的一个bug,在这里分享一下!
在我们的实测中发现:在加载资源的时候如果使用延迟绑定的方式显示UI,在UnityEditor模式下UI的prefab加载显示后所有图片都是白图!但是发布到设备中能正确显示。
莫非延迟绑定只能运行时使用?
Texture Packer
Texture Packer最终的解决方案,当然这也是很早以前就使用的方法了。如果Unity能把这件事做好,我相信大家都不想自己单独用第三方软件去搞图集。TexturePacker具体功能和使用方法就不多说了,网上相关教程有很多。
这里我只说一下TexturePacker解决了Unity的哪些问题:
1.图集打包算法,选择很多,也更专业。
2.动态加载图片,简单明了。编辑时加载:AssetDatabase.LoadAllAssetsAtPath()或者AssetDatabase.LoadAllAssetRepresentationsAtPath();运行时加载:AssetBundle.LoadAllAssets()
3.图集的依赖关系,很直观。
当然也有缺点:
需要维护TexturePacker工程文件。
总结一下:
SpritePacker,商业项目可用,需要自己做点东西“填坑”。
SpriteAtlas,商业项目可用,他解决了SpritePacker的小问题,但是自己有带来了新问题,如果“白图”的bug解决不了,可能需要单独写一套编辑时的加载流程。感觉和SpritePacker填的坑差不多!
TexturePacker,商业项目可以,相对来说比较“健康”,不用额外写代码填坑。
从本文还可以看出一点,Unity对UI的重视程度还是比较小的!
就说到这里吧!Have a good day!
UGUI的图集处理方式-SpriteAtlas的前世今生的更多相关文章
- Unity 利用UGUI打包图集,动态加载sprite资源
今天做了一个UI界面,这个界面是好友界面,该界面上有若干个好友item. 需要对每个tem的头像对象(image)动态显示对应的头像.尝试利用UGUI的图集来加载,具体实现如下: 1.首先,需要知道S ...
- UGUI 打图集
using UnityEngine; using System.Collections; using UnityEditor; using System.Collections.Generic; us ...
- [置顶]
Unity2d引入新功能SpriteAtlas,Sprite新的图集方式
孙广东 2017.8.3 http://blog.csdn.NET/u010019717 在Unity 2017.1.0f3中引入了 SpriteAtlas 官方文档: https://docs. ...
- 【Unity游戏开发】SpriteAtlas与AssetBundle最佳食用方案
一.简介 在Unity步入2019.4以后,新版的SpriteAtlas日趋完善,已经完全可以在商业项目中使用了.但是纵观网络平台上,许多关于SpriteAtlas的文章还停留在2018的初版时期,其 ...
- 如何快速优化手游性能问题?从UGUI优化说起
WeTest 导读 本文作者从自身多年的Unity项目UI开发及优化的经验出发,从UGUI,CPU,GPU以及unity特有资源等几个维度,介绍了unity手游性能优化的一些方法. 在之前的文 ...
- ugui的优化
参考文章 https://www.jianshu.com/p/061e67308e5f https://www.jianshu.com/p/8a9ccf34860e http://blog.jobbo ...
- (转)Unity 之 UGUI 小总结
转自:http://www.jianshu.com/p/5b6f5022662e 开发过程中对UGUI的一个小总结. 首先从原画师拿到效果图,美术切图,拿到碎图后打成大图. 我们先来说一下图:RGBA ...
- 关于Unity中的UGUI优化,你可能遇到这些问题
https://blog.uwa4d.com/archives/QA_UGUI-1.html 关于Unity中的UGUI优化,你可能遇到这些问题 作者:admin / 时间:2016年11月08日 / ...
- UGUI研究院之控件以及按钮的监听事件系统
继续学习,我相信大家在做NGUI开发的时候处理事件都会用到UIEventListener,那么UGUI中怎么办呢?先看UGUI的事件有那些吧 Supported Events The Eventsys ...
随机推荐
- 安装解压版MySQL5.76及以上版本 出现服务正在启动-服务无法启动的问题
最近重装了系统,去MySQL官网下载了最新的MySQL5.7.9,我选择的是解压版,安装之后启动服务的时候,提示服务无法启动,在网上找了很多教程,弄了很久都没有弄好,后来还是决定去英文官网找找答案, ...
- 用python输出回文数
一个b站上的朋友问我,怎么返回五位数的回文数的个数. 我首先百度回文数的概念,就是正读和倒读都一样的数字,例如:10001,99899 等等 数字的位数拆分一头雾水,思来想去,用字符串的方法完美解决! ...
- 段落超出div部分隐藏显示
overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
- 访问腾讯云主机mysql的设置问题
---恢复内容开始--- 1.需要打开腾讯云主机的防火墙端口3306,具体实现可以在腾讯云控制台安全组中设置开放全部端口(安全组对应入站.出战规则): 2.将云主机mysql中mysql数据库user ...
- js里的window对象
alert(<msg>) 向用户显示对话框窗口并等候其被关闭 blur() 让窗口失去键盘焦 ...
- 网站性能优化的方法--Yahoo
如何能让用户更快的打开我们的网页? 1.尽可能减少HTTP请求数 2.使用CDN(内容分发网络) 3.添加Expire/Cache-Control头 4.启用Gzip压缩 5.将CSS放在页面最上面 ...
- 【Android】Fresco 初次使用遇到的坑
初次使用开源框架 Fresco,结果遇到了坑,被虐了半下午--暂且记下. 下面的错误 android.view.InflateException: Binary XML file line #** 报 ...
- 向.Net/Unity 程序员推荐一个十分因吹斯听的网站:sharplab.io
0x00 前言 & 过程 & 结论 今天发现了一个十分有趣的网站: https://sharplab.io/ 网站的页面并不复杂,功能大体上能够在题图中得到概括.发现它的过程也很偶然, ...
- 重启iis的命令是什么?三种简单的重启方式
第一种.界面操作 打开“控制面板”->“管理工具”->“服务”.找到“IIS Admin Service” 右键点击“重新启动” 弹出 “停止其它服务” 窗口,点击“是”. 第二种.Net ...
- 通过Powershell修改文件默认打开方式
修改原理 详情: Windows下通过注册表修改某个类型文件的默认打开方式和文件图标 脚本详情: Github:Change_default_programs.ps1 描述: 至少在Windows10 ...