最糟糕的是人们在生活中经常受到错误志向的阻碍而不自知,真到摆脱了那些阻碍时才能明白过来。 —— 歌德


说到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的前世今生的更多相关文章

  1. Unity 利用UGUI打包图集,动态加载sprite资源

    今天做了一个UI界面,这个界面是好友界面,该界面上有若干个好友item. 需要对每个tem的头像对象(image)动态显示对应的头像.尝试利用UGUI的图集来加载,具体实现如下: 1.首先,需要知道S ...

  2. UGUI 打图集

    using UnityEngine; using System.Collections; using UnityEditor; using System.Collections.Generic; us ...

  3. [置顶] Unity2d引入新功能SpriteAtlas,Sprite新的图集方式

    孙广东  2017.8.3 http://blog.csdn.NET/u010019717 在Unity 2017.1.0f3中引入了 SpriteAtlas 官方文档:  https://docs. ...

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

    一.简介 在Unity步入2019.4以后,新版的SpriteAtlas日趋完善,已经完全可以在商业项目中使用了.但是纵观网络平台上,许多关于SpriteAtlas的文章还停留在2018的初版时期,其 ...

  5. 如何快速优化手游性能问题?从UGUI优化说起

    WeTest 导读   本文作者从自身多年的Unity项目UI开发及优化的经验出发,从UGUI,CPU,GPU以及unity特有资源等几个维度,介绍了unity手游性能优化的一些方法.   在之前的文 ...

  6. ugui的优化

    参考文章 https://www.jianshu.com/p/061e67308e5f https://www.jianshu.com/p/8a9ccf34860e http://blog.jobbo ...

  7. (转)Unity 之 UGUI 小总结

    转自:http://www.jianshu.com/p/5b6f5022662e 开发过程中对UGUI的一个小总结. 首先从原画师拿到效果图,美术切图,拿到碎图后打成大图. 我们先来说一下图:RGBA ...

  8. 关于Unity中的UGUI优化,你可能遇到这些问题

    https://blog.uwa4d.com/archives/QA_UGUI-1.html 关于Unity中的UGUI优化,你可能遇到这些问题 作者:admin / 时间:2016年11月08日 / ...

  9. UGUI研究院之控件以及按钮的监听事件系统

    继续学习,我相信大家在做NGUI开发的时候处理事件都会用到UIEventListener,那么UGUI中怎么办呢?先看UGUI的事件有那些吧 Supported Events The Eventsys ...

随机推荐

  1. JAVA-1.连接数据库

    import java.sql.*; import com.mysql.jdbc.Driver; /* * <JDBC基础篇> * 连接数据库一般来说分为6个步骤: *1-加载驱动 *2- ...

  2. Java类什么情况下被初始化?

    1.创建类的实例(new 的方式).访问某个类或接口的静态变量,或者对该静态变量赋值,调用类的静态方法 2.反射的方式 3.当初始化一个类的时候,如果发现其父类还没有进行初始化,则需先触发其父类的初始 ...

  3. 温故而知新,重温 Java 7 的那些“新”特性

    2009 年 4 月 20 日,Java 的亲生父亲 Sun 被养父 Oracle 以 74 亿美元收购,这在当时可是一件天大的事.有不少同学都担心 Java 的前途,我当时傻不啦叽地也很担心:自己刚 ...

  4. [算法]LeetCode 1.两数之和

    LeetCode 1.两数之和(python) 1.朴素解法 最朴素的两个for循环大法: class Solution: def twoSum(self, nums: List[int], targ ...

  5. 终极版Servlet——我只能提示您路过别错过

    终极版Servlet 前言:这两天看了SSM框架,本来是想往后继续学的,脑门一转又回来了,不能就这么不声不响的走了,看了这么多天的Servlet,再写最后一篇做个告别吧,这篇起名为终极版,是我现在所能 ...

  6. 【iOS】ARC & MRC

    iOS 项目类型,是 ARC 还是 MRC 未完……

  7. [重磅开源] 比SingleR更适合的websocket 即时通讯组件---ImCore开源了

    有感而发 为什么说 SignalR 不合适做 IM? IM 的特点必定是长连接,轮训的功能用不上. 因为它是双工通讯的设计,用hub.invoke发送命令给服务端处理业务,其他就和 ajax 差不多, ...

  8. ECharts图表插件(4.x版本)使用(一、关系图force节点显示为自定义图像/图片,带分类选择)

    导读 ECharts,一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safar ...

  9. [nghttp2]压测工具,源码编译并进行deb打包过程

    编译环境:deepin 15.11桌面版 nghttp2下载地址:https://github.com/nghttp2/nghttp2 环境要求 emm只能在类Linux环境才能完整编译,想在Wind ...

  10. Tomcat源码分析 (一)----- 手写一个web服务器

    作为后端开发人员,在实际的工作中我们会非常高频地使用到web服务器.而tomcat作为web服务器领域中举足轻重的一个web框架,又是不能不学习和了解的. tomcat其实是一个web框架,那么其内部 ...