Version: 1.4
语言 : 中文
UOS文件上传和下载
使用说明

TextureManager

Texture Manager 功能模块:

  • 帮助解决游戏项目中纹理资源使用不合理、资源包纹理资源冗余等原因导致的显存消耗问题
  • 同一套 AssetBundle 可以支持多套纹理(每套纹理针对不同平台使用不同的压缩格式)

功能介绍

多压缩格式支持

小游戏有同时运行在手机和桌面设备的需求。使用单一的 ASTC 压缩格式在桌面端运行时,ASTC 格式的纹理需要先解压成对应未压缩的纹理格式然后再上传 GPU 。解压过程在主线程执行,会带来严重的卡顿问题;上传未压缩的纹理到 GPU , 也会导致显存的浪费(显存占用超过4倍)。

TextureManager 可以批量生成多种压缩格式的纹理数据,例如 ASTC4x4 + ASTC8x8 + DXT。 游戏运行时,TextureManager 模块开始初始化,贴图对象会根据以后信息和用户平台设定的纹理格式信息初始化 Metadata 信息,但是不会分配存储纹理数据。而后当纹理需要加载上传纹理数据时,引擎可以自动根据当前平台、设备性能选择合适的压缩格式进行下载使用。

启用 TextureManager 后,Assetbundle 只保留纹理的 metadata 信息,纹理数据被剥离出去。在 Assetbundle 打包好后,假如需要调整支持的纹理压缩格式,无需重新打包 AssetBundle 。

显存预算控制

TextureManager 支持设置纹理显存用量上限。当显存用量达到预设时,会根据策略计算纹理的分值并排序,优先从 GPU 上踢出低分值纹理。计算分值时会考虑:

  • 纹理导入时制定的上传模式( Immediately,Reference,Renderer )
  • 纹理导入时指定的优先级( Renderer 模式 )
  • 纹理 Renderer 可见性或者被 UI 引用情况
  • 纹理 Renderer 与相机的距离

生命周期管理

之前,在调用 Assetbundle.LoadAsset(Async)SceneManager.LoadScene(Async)Resource.Load(Async)等接口加载资产后,引擎会依次:

  1. 创建纹理对象;

  2. 读纹理内容进内存;

  3. 并将纹理内容上传至GPU,调用Assetbundle.Unload(true)Resource.UnloadUnusedAssets()时,执行:
    • 从GPU上释放纹理显存

    • 销毁纹理对象

    为了控制显存占用,需要用户管理好纹理的生命周期(通常是在用户代码中做好引用计数):

    • 在小游戏平台频繁调用 Resource.UnloadUnusedAssets() 会带来严重卡顿问题;
    • 使用AssetBundle.Unload(true) 对 AssetBundle 的组织结构要求较高;
    • 当 bundle 中存在多个资源时,难以实现对单个纹理生命周期的控制。

启用 TextureManager 后,操作序列将变为:

  1. 创建纹理对象
  2. 下载纹理进缓存(当缓存命中时跳过此步)
  3. 读纹理内容进内存
  4. 并将纹理内容上传至GPU

其中步骤 2~4 将延迟至引用纹理的 Renderer 可见时(或引用纹理的UI被绘制时)再执行。

为避免同时处理大量纹理带来的卡顿与内存峰值,TextureManager 会进行分帧平滑调度,将这些操作分配到多帧中。

TextureManager 仅对纹理的 GPU 显存进行管理,不改变纹理对象的生命周期,纹理对象本身仍由原有的逻辑控制。 如下图所示,当纹理闲置,即当纹理 Renderer 不可见或者当前绘制 UI 对纹理的引用为0时,Texture Manager 标记纹理为可卸载,超出显存预算时将从 GPU 显存中卸载。当纹理重新处于渲染状态时,TextureManager 会再次执行步骤 2~4 ,上传纹理内容到 GPU 用于绘制。

纹理重映射

为了解决小游戏中的纹理冗余问题,TextureManager 在上传纹理到 GPU 前会先查看是否已有同样的纹理。发现重复纹理的情况下,会在底层进行映射,使其共用 GPU 上的同一张纹理,从而避免纹理冗余带来的显存开销。

使用限制

  • 暂不支持 unity spritealtas ,仅支持原生美术制作的图集
  • 暂不支持 Texture Shape 为 3D 和 2D Array 的图片资源类型;
  • 资源的 upload by reference 模式,仅在 UGUI 和 NGUI 上测试验证过;
UOS文件上传和下载
使用说明