【unity】动态图集 dynamic atlas (runtime atlas)

本文探讨了Unity中动态图集(runtime atlas)的概念,如何解决静态图集在内存和合批上的问题。通过动态生成图集,减少ABA图集穿插,优化内存使用。虽然存在生成成本和碎片化等问题,但通过示例展示了动态图集在降低DrawCall方面的优势。源码中的关键在于Graphics.CopyTexture的快速GPU操作。配合自定义的NxImage,实现了引用计数管理。
摘要由CSDN通过智能技术生成

不管NGUI还是UGUI,图集都是在制作期间就生成了的,运行时是一张大图,这样做的好处在于我们可以在一定程度上去合并批次,但是图集通常在制作过程中,会分成commonatlas和系统atlas两类,一个界面prefab至少会用到两张图集,就会出现ABA的图集穿插打断合批的情况。还有一种游戏内容多了以后,各种图片也相应的变多,类似图标、commonatlas这种图集,一张2048x2048可能就放不下了,这时候如果用到两张2048x2048,就又出现了之前说的ABA的情况,而且内存上也上去了。这时候就出现了新的解决方案:动态图集。

动态图集其实就是我们在打包的时候,图片是零散的,但是最后运行时,自动生成一张空白大图片,然后将界面上用到的零散的图片绘制在这个大图上,只将这个大图传入到gpu里头,达到合批的效果。由于手机界面制作过程中,标准分辨率往往是低于2048的,所以一张2048的动态图集就能完全解决一个界面的绘制工作了,但是动态图集也是有缺点的,动态图集因为将图集的生成过程延迟到了游戏运行时,所以必然会比静态图集多了图集生成的成本,当然这也是可以优化的。并且在目前的动态图集生成方案中,还没有出现公开的支持压缩的动态图集解决方案,所以动态图集目前看来只能是RGBA32的格式。还有一点,静态图集由于图片在生成过程中是确定的,可以将分配算法做得很好,图集的利用率也能做到很高。动态图集由于图片是动态生成的,在游戏运行过程中也会动态的增减图片,类似操作系统的内存分配算法,图集必然会出现碎片,图集的利用率也不可能做得很高。

说了那么多 就做个demo来看看动态图集的威力吧。

 

这个demo只是简单的演示一下动态图集的主要思路,图片分配算法也只是将大图片分成128x128的一个一个分区,每个分区采用引用计数开控制是否在使用图片,用于维护整个UI系统的话,这种算法并不适用,但是如果只是用于icon图标的话,由于icon图标是固定尺寸的,所以这套算法就很合适了。下面上源码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NxSpriteInfo
{
    private int _x;
    private int _y;
    private Sprite _sprite;
    private int _referenceCount;

    private int _width;
    private int _height;

    public int x { get { return _x; } }
    public int y { get { return _y; } }

    public Sprite sprite
    {
        get { return _sprite; }
    }

    public NxSpriteInfo(int x, int y, Texture2D mainTexture, int startX, int startY, int width, int height)
    {
        _x = x;
        _y = y;
        _referenceCount = 0;

        _width = width;
        _height = height;

        _sprite = Sprite.Create(m
Unity中,当你创建一个Sprite Atlas并使用它来打包多个Sprite时,你可能需要获取这个图集在构建后占用的具体大小。这可以通过编写脚本来实现,以便在构建过程之后获取图集的大小信息。以下是如何通过脚本实现这一功能的基本步骤: 1. 在Unity编辑器中,创建一个新的C#脚本,命名为例如`SpriteAtlasSizeReporter.cs`。 2. 将这个脚本附加到一个空的GameObject上。 3. 在脚本中,你需要使用`Resources.Load`方法来加载你的Sprite Atlas资源。 4. 之后,使用Unity的`SpriteAtlas.GetPackedSheet`方法来获取图集的详细信息。 5. 通过这些信息,你可以计算出图集的总宽度和高度,这通常基于图集中的每个元素的大小以及它们如何被排列。 以下是一个简单的代码示例,展示了如何获取Sprite Atlas的打包后的图集大小: ```csharp using UnityEngine; using UnityEngine.U2D; using UnityEngine.SpriteRuntimeAtlas; public class SpriteAtlasSizeReporter : MonoBehaviour { void Start() { // 加载指定的Sprite Atlas资源 SpriteAtlas atlas = Resources.Load<SpriteAtlas>("YourSpriteAtlasName"); if (atlas == null) { Debug.LogError("Sprite Atlas not found!"); return; } // 获取图集的打包信息 PackedSheet packedSheet = atlas.GetPackedSheet(); if (packedSheet == null) { Debug.LogError("Could not get packed sheet for the atlas."); return; } // 计算图集的大小 int totalWidth = packedSheet.rect.width; int totalHeight = packedSheet.rect.height; Debug.Log($"Sprite Atlas Size: {totalWidth} x {totalHeight}"); } } ``` 请将`"YourSpriteAtlasName"`替换为你的实际Sprite Atlas的名称。 在使用上述脚本之前,确保你的Sprite Atlas已经被正确添加到Resources文件夹中,以便可以通过`Resources.Load`方法加载。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值