本文分享Unity中的资源管理-资源类型和基本使用

真不容易, 经过几篇文章的铺垫, 我们终于进入正题了.

今天继续给大家聊聊资源管理中的基础知识: 资源的类型和基本的使用.

Unity中的资源类型

这一部分在官方文档里介绍的很清楚, 有兴趣的同学可以自行跳转:

unity获取资源所有依赖 unity的资源_unity获取资源所有依赖

如果不愿意看官网, 以下我们简单做一下梳理和总结. 大家也可以有个大致的印象.

Unity常见的资源类型有:

  • Texture(纹理), Sprite(精灵): BMP、TIF、TGA、JPG、PNG 和 PSD
  • Sound(音效): Mp3, Wav, OGG, AIFF
  • Fbx(模型): Dae、3ds、Dxf、Obj、Max
  • Mesh(网格)
  • Animation(动画), Animator(动画控制器)
  • Font(字体): TTF, BMFont, Fnt
  • Shader(着色器)
  • Meterial(材质)
  • Prefab(预制)

其中大部分不需要实例化, 加载完成即可使用.

各种资源导入Unity之后, Unity会对其进行一些配置, 比如音效和图片在不同平台下的压缩方式, 图片是按照纹理方式还是按照精灵方式使用等.

Unity不会使用资源的原始版本, 而是对每个资源进行配置, 即所谓AssetImporter, 并生成对应的.meta文件用于描述, 最后在Library中生成最终在Unity使用的资源, 在发布时和运行时, 使用的是Unity生成的版本.

我们可以重写各种AssetImporter, 从而在各种资源导入时做自定义的逻辑, 比如导入图片时, 默认将其按照文件夹制作为图集(Atlas).

下面是一张图片的导入设置:

本文分享

unity获取资源所有依赖 unity的资源_unity_02

第一个红圈代表这个图片的类型, 是纹理还是精灵等.

第二个红圈是在各个平台下的压缩设置.

下面是其对应的.meta文件内容:

unity获取资源所有依赖 unity的资源_资源管理_03

.meta文件描述了图片信息和使用方式, 比如上面包含了文件的唯一ID, 导入设置信息等. 这里只截取部分, 更多的内容有机会我们单独再讨论.

本章节只是对资源类型进行简单的举例和梳理总结, 大家目前只需要知道:

  • Unity中支持各种类型的资源
  • 每个资源在导入后都会生成一个对应的配置文件.meta
  • Unity不直接使用资源的原始文件, 而是根据导入配置重新生成Unity中统一使用的资源
  • 可以重写某种类型资源的导入设置, 添加自定义部分
  • 大部分资源加载后即可直接使用, 少部分需要实例化后使用

资源加载和卸载的几种方式

在Unity中, 有几种资源的加载方式, 各有各的适用范围. 主要涉及到几个类的使用:

  • Resources
  • AssetBundle
  • AssetDatabase
最简单的加载卸载方式: Resources

将资源放在Assets/Resources目录(可以自行创建)后, 就可以直接使用Resources.Load("path")加载资源并使用, 且不需要文件扩展名.

使用Resources.UnloadAsset(obj)卸载资源, 需要传入资源对象.

使用Resources.UnloadUnusedAssets()卸载资源所有不再使用的资源.

这种方式最为简单, 但是该目录下的资源大小不能超过2G, 如果游戏比较小, 就可以采用这种方式, 可以极大减小资源管理的复杂度.

因为这种方式最简单, 也最快, 所以可以结合其它方式使用, 比如将基本不会变的或者游戏启动时必要的少量资源使用这个方式,然后经常变动的资源使用Ab, 最后通过热更新替换资源.

这种方式提供同步和异步加载接口.

大型项目使用最多的加载卸载方式: AssetBundle

小型项目使用Resources.Load已经足够, 但是这只是一种很粗粒度的资源管理, 在大型项目中却显得不是那么好用.

在大型项目中, 一般会使用热更的方式更新资源, 而且资源之间的依赖和管理需求更加细致, 我们需要对资源进行分类, 分块管理.

AssetBundle就是Unity提供的一种针对大型项目的资源管理方案(当然, 小项目也可以使用), 将资源分类, 分块的组织起来有条不紊的管理.

AssetBundle是将资源按照类型或者文件夹构建出一个资源包(就是所谓AssetBundle, Ab, 资产包), 使用时先加载Ab, 然后从Ab中加载资源.

使用AssetBundle.LoadFromFile("abPath")加载ab, 需要传入ab包全路径, 如Assets/Output/AssetBundle/AllAb/123.asset.

使用assetBundle.LoadAsset("fileName")从ab加载资源, 需要传入文件名(带不带后缀都可以), 或者文件全路径, 如obj.prefab或者obj或者Assets/Res/Prefabs/obj.prefab.

使用assetBundle.Unload(true or false)卸载Ab, 需要传入是否需要同时销毁从Ab中加载的资源.

使用AssetBundle.UnloadAllAssetBundles(true or false)一次性卸载所有Ab, 参数意义与上面一致.

使用Resources.UnloadAsset(obj)卸载从Ab中加载的资源.

使用Resources.UnloadUnusedAssets()卸载资源所有不再使用的资源.

简单说就是:

  • 先加载Ab, 然后从Ab中加载资源
  • 使用Resources卸载从Ab中加载的资源, 当然也可以卸载不是从Ab中加载的资源
  • 使用Ab卸载自己, 也可以同时一次性卸载从Ab中加载的所有资源

我们会用专门的文章讨论Ab, 这里只是一个简要说明.

这种方式提供同步和异步加载接口.

Editor下的加载和卸载方式: AssetDatabase

我们开发时大部分情况处于Editor模式下, 如果每次修改资源后都需要打Ab, 然后再调试, 这样会极大的降低开发效率, 所以在Editor模式下一般会使用AssetDatabase或者Resources进行资源加载和卸载.

使用AssetDatabase.LoadAssetAtPath("path")加载资源, 提供文件全路径, 如Assets/Res/Prefabs/obj.prefab.

使用Resources.UnloadAsset(obj)卸载资源, 需要传入资源对象.

使用Resources.UnloadUnusedAssets()卸载资源所有不再使用的资源.

这里简单提一下, 早期是不存在AssetDatabase这种资源管理方式的, 它是建立在Resources的基础之上, 在某些Unity版本中, Resources还保留了部分AssetDatabase接口, 只是被标记为弃用了.

当然, AssetDatabase还有很多其它接口, 我们将在其它文章讨论.

资源(Resource)和资材(Asset)

Unity中所有对象都可以被称为资源(Resource), 包括静态的和动态的.

其中静态的资源, 就是说可以持久化的资源, 被单独称为资材(Asset), 资材本身也是一种资源.

动态的资源就是游戏运行过程中, 动态生成的对象. 这些对象可以使用资材, 然后序列化下来变成新的资材.

简单的说就是:

  • 使用资材相关接口加载资材, 产生资材的引用对象:
  • obj = Resources.Load(...)
  • obj = assetbundle.LoadAsset(...)
  • obj = AssetDatabase.LoadAssetAtPath(...)
  • 使用资源卸载接口卸载资材的引用对象:
  • Resources.UnloadAsset(obj)
  • Resources.UnloadUnusedAssets()
  • 或者卸载Ab的时候, 顺便卸载资材的引用对象
  • assetBundle.Unload(true)
  • AssetBundle.UnloadAllAssetBundles(true)

但是这里有一类特殊的资材, 包括:

  • 游戏对象(GameObject)或者组件(Component): 以预制或者模型等形式存在
  • AssetBundle

这一类资材通常需要实例化后使用(AssetBundle除外), 且没有单独的卸载接口, 只能进行批量卸载, 其的正确卸载方式如下:

  • 销毁其实例化出来的游戏对象: Object.Destroy(obj); obj = null;
  • 使用Resources.UnloadUnusedAssets()卸载
  • 或者使用assetBundle.Unload(true)卸载

总结

今天简单的给大家介绍了下Unity中资源相关的基础概念, 只是提纲挈领的给大家一个先期印象, 详细的内容请参考官方文档或者后续的文章.

未来几篇文章会讨论我们资源管理的主要方式, AssetBundle, 从打包, 同步加载, 异步加载, 卸载和简单使用, 请大家继续关注.

好了, 今天的内容就是这些, 希望对大家有所帮助.