Unity-通过AB包使用SpriteAtlas图集(基于unity2018)

项目遇到了一个性能问题,需要优化UI。其中就涉及UI的合批问题,其中自然而然就会关联到图集的概念。旧版图集,Legacy Atlas,还没有太研究。今天主要看一下SpriteAtlas怎么使用的。

因为我们项目资源工程和Runtime是分离的,所以所有的资源都需要通过AssetBundle加载。

我们做个Demo工程

一个prefab,有三个Image,分别引用了三个Card文件夹下的图片

Card目录如下:

然后我们把prefab单独打一个包,把Cards单独打一个包。

这里先记录一下,打包的大小,然后用AssetStudio看一下ab包里的组成

在运行时我们通过AssetBundle把prefab加载出来

可以看出来,图片是没有合批的,因为没有打图集.

然后我们建立一个图集,把Cards拖动进去

这里勾上Include in Build。让图集自动引用打进AB包

再次构建

发现Card的大小变小了。但是在Manifest里,是看不到任何跟图集有关的信息的,那我们用AssetStudio打开看一下,可以看到图集确实在AssetBundle里了

运行时:

可以看到,已经正确合批了。

不过请注意,我是在Editor上测试的,需要再ProjectSetting里打开Atlas的Always Enabled才能看到效果。不管是不是用AB包加载的。

这个时候我们换一下尝试,如果我们勾选Include in Builds的同时,并且把Atlas的这个图集也打成AB包,会怎么样?

可以看到,本来在card里的图集信息跑到了atlas里

通过manifest的引用关系可以看到。Card没有引用atlas,而是atlas引用了Card。好。那么我们进游戏再加载prefab,注意。prefab只引用了card。二者都没有引用atlas,我们看看会不会有用

结果是正常加载了,这就很奇怪。谁加载的AssetBundle啊?我们通过MemoryProfiler发现

有一张大图集被一个叫CachedSpriteAtlasRuntime的引用着。根据之前查的资料,该不会是缓存吧。或者我的Editor下数据被关联了?于是我把工程里的Atlas文件删掉,只保留ab包里的,果然,效果就不对了

这就比较纠结了。Editor下的资源竟然参与Build了。这就没办法了。那只能打包测试了,打包成andorid以后测试,果然,还是白色的

因为打包成AB以后,实际上是需要自己去处理这个bundle依赖的。所以在加载Prefab之前,先把atlas的AssetBundle也Load出来,显示就正确了。

好。现在再考虑一个问题,如果我不勾选Include in Builds,会怎样。我们做个测试

变成白色了,即便我们提前加载了Atlas的AssetBundle,还是不行。

但是这个时候是触发了官方说的延迟绑定回调了

其实在上一步,如果你不提前加载AssetBundle,也会触发延迟绑定回调

我们处理下延迟绑定的内容

加上代码以后:

    private void Awake()
    {
        SpriteAtlasManager.atlasRequested += OnAtlasRequested;
    }

    private void OnAtlasRequested(string atlasName, Action<SpriteAtlas> callback)
    {
        Debug.LogError("AtlasRequested");
        _atlas = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/atlas");
        SpriteAtlas atlas = _atlas.LoadAsset<SpriteAtlas>(atlasName);
        callback(atlas);
    }

可以看到,在手机上,或者在Editor上,如果你删除了对应的图集,就会触发这个延迟绑定回调。这个时候,你需要把SpriteAtlas回调回去,才可以正确显示,如下图所示

可以看到,中间加载是有一帧是白色的,一点都不平滑。所以这种方式其实不是很推荐。

好了,至此为止,我们已经完成了对Atlas的测试,下边进行总结一下包括认为的最佳实践:

1、SpriteAtlas在AB包统计引用的时候,不会被正确统计依赖,SpriteAtlas会引用贴图,但是Prefab和贴图本身不会依赖SpriteAtlas,所以如果SpriteAtlas单独打,就需要做额外的引用关系维护处理。

2、所以怎么办呢?每个UI单独建立一个文件夹,来存放预制上美术的直接引用(非通过代码动态加载并设置sprite的情况),然后直接把SpriteAtlas打在这个文件夹内,可以通过代码去创建SpriteAtlas来做自动化。不知道的可以自己搜一下。然后对这个整个文件夹打成一个AB包,这样,预制加载的时候,会引用到里边的图片,图片所在的ab加载了,里边的SpriteAtlas也会被正确引用到。它俩生命周期是一致的,没必要单独打。

完结!

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-30 08:08:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-30 08:08:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-30 08:08:02       82 阅读
  4. Python语言-面向对象

    2024-03-30 08:08:02       91 阅读

热门阅读

  1. Tomcat

    Tomcat

    2024-03-30 08:08:02      32 阅读
  2. MacOS安装Homebrew教程

    2024-03-30 08:08:02       34 阅读
  3. 在Oracle中如何使用索引快速扫描优化全表扫描

    2024-03-30 08:08:02       45 阅读
  4. 代码随想录算法训练营 Day35 贪心算法4

    2024-03-30 08:08:02       41 阅读
  5. 中央处理器CPU

    2024-03-30 08:08:02       39 阅读
  6. 【OpenCV】Mat 构造函数

    2024-03-30 08:08:02       41 阅读
  7. Redis 过期删除策略 And 内存淘汰策略 !!!

    2024-03-30 08:08:02       39 阅读
  8. Docker从入门到放弃

    2024-03-30 08:08:02       36 阅读
  9. 2024年github开源top100中文

    2024-03-30 08:08:02       38 阅读
  10. Qt学习建议

    2024-03-30 08:08:02       34 阅读