资源管理
大致分为四类: Resources、StreamingAssets、AssetBundle、PersistenDataPath
-
Resources
- 作为保留文件夹出现,放在这个文件的东西在打包时都会被无条件地打包到发布包中
- 特点:
- 只读(想要动态更新的资源不要放这)
- 会将文件夹内的资源打包集成到.asset文件里面。(可以放prefab,prefab在打包时会自动过滤不需要的资源)
- 主线程加载
- 资源读取用
Resources.Load()
-
StreamingAssets
- 作为保留文件夹出现,和Resources最大区别就是,Resources打包时会压缩和加密,而StreamingAssets则会原封不动的打入包中
- 使用
Application.streamingAssetsPath
来获得这一文件夹路径。在Unity工程中, 放在StreamingAssets文件夹中的任何资源都将被原样复制到目标设备上的一个特定文件夹中- 特点:
- 只读
- 主要存放二进制文件 (txt、xaml、json)
- 只能用www来读取
- 特点:
-
AssetBundle
- 是unity定义的一种二进制类型,可以把Prefab或二进制文件封装成AssetBundle文件,其中包含模型、贴图、预制体、声音、甚至整个场景,可以在游戏运行的时候被加载。
- 它是一个 Assetbundley对象,我们可以通过代码从一个特定的压缩包加载出来的对象。这个对象包含了所有我们当初添加到这个压缩包里面的内容,我们可以通过这个对象加载出来使用
- 特点:
- 是unity定义的一种二进制类型
- 最好将Perfab封装成AssetBundle
- 使用www类下载
-
PersistentDataPath
- 可以在运行后进行读写,由于这个特性,可以将需要热更的文件放在里面
- 特点:
- 可读写。不过只能运行时才能读写。提前放入不可
- 无内容限制。可以从AssetBundle或StreamingAssets里读取出来,放入其中进行热操作
- 写下的文件可以再电脑上查看。同样也可以清掉
unity中获取文件路径
Application.dataPath
:获取当前Assets文件路径 (一般用在pc)Application.streamingAssetsPath
:获取StreamingAssets文件路径(一般用在手机上)Application.persistentDataPath
: 目标平台 可读可写- Android: SD卡
- Ios:Document
- Pc:C:\Users\Administrator\AppData
具体路径可参考这篇文章 ->传送门
Resources使用
- 常用API
函数名 | 作用 |
---|---|
LoadAll | 从Resources文件夹内加载所有资源 |
Load | 从Resources文件夹内加载一个路径的资源 |
LoadAsync | 同Load 加载方式是异步操作 |
UnloadAsset | 从内存中卸载指定资源 |
UnloadUnusedAssets | 从内存中卸载未使用的资源(无引用) |
LoadAll:加载Resources目录下的asset,
//加载Prefab目录下的所有对象
var prefabs = Resources.LoadAll("Prefab");
//加载Prefab目录下的所有GameObject对象
GameObject[] prefabs1 = Resources.LoadAll<GameObject>("Prefab");
- Load:加载单个asset (三种方式)
var c = Resources.Load ("Cube");
var c = Resources.Load<GameObject> ("Cube");
var c = Resources.Load ("Cube") as GameObject;
GameObject.Instantiate (c, Vector3.zero, Quaternion.identity);
- LoadAsync: 异步加载 需要协程 返回一个ResourcesRequest
StartCoroutine(LoadAsyncTest());
public IEnumerator LoadAsyncTest () {
ResourceRequest resource = Resources.LoadAsync ("Cube");
yield return resource;
GameObject.Instantiate (resource.asset, Vector3.zero, Quaternion.identity);
}
AssetBundle使用
-
基本打包设置
编写基本代码,把这个脚本放入Editor文件夹(没有自建),因为没有继承MonoBehaviour所以这个文件不参与打包和发布的。(属于编辑器拓展)using System.IO; using UnityEditor; public class BuildAssetBundle { [MenuItem ("Assets/BuildAssetBundls")] static void CreateAssetBundles () { string dir = "AssetBundles"; //如果路径不存在就创建 if (Directory.Exists (dir) == false) Directory.CreateDirectory (dir); /**用这个方法进行打包 第一个参数为打包到目标文件 第二个参数为打包选项 第三个参数为打包的目标平台 */ BuildPipeline.BuildAssetBundles (dir, BuildAssetBundleOptions.None, BuildTarget.iOS); } }
-
BuildeAssetBundleOptions
选项:- Buildassetbundleo ptionsBuildassetbundleoptions.None:使用LZMA算法压缩,压缩的包更小,但是加载时间更长。使用之前需要整体解压。旦被解压,这个包会使用LZ4重新压缩。使用资源的时候不需要整体解压。在下载的时候可以使用LZMA算法,一旦它被下载了之后,它会使用LZ4算法保存到本地上
- BuildassetbundleOptions.Uncompressedassetbundle:不压缩,包大,加载快
- BuildassetbundleOptions.Chunk Compression:使用LZ4压缩,压缩率没有LZMA高,但是我们可以加载指定资源而不用解压全部。注意使用LZ4压缩,可以获得可以跟不压缩想媲美的加載速度,而且比不压缩文件要小
-
ab包创建测试。
在unity中创一个Cube并设置为预设体(Perfab)来做测试。左键单击选中预设体,在Inspector界面最底部会看见AssetBundle 如👇图
创建包名和拓展名,其中如果不写路径,默认存在一级目录 ,其中拓展名随意(一般是unity3d)
菜单栏选中 “Assets/BuildAssetBundls” 生成
-
加载AssetBundle
- 常用API
函数名 | 作用 |
---|---|
LoadFromMemoryAsync | 从内存中异步加载 |
LoadFromMemory | 从内存中同步加载 |
LoadFromFileAsync | 从文件中异步加载 |
LoadFromFile | 从文件中同步加载 |
LoadFromMemoryAsync:从内存加载需用协程
StartCoroutine (CreateAsset ());
IEnumerator CreateAsset () {
var path = "AssetBundles/test/cube.unity3d";
//返回一个请求
AssetBundleCreateRequest request = AssetBundle.LoadFromMemoryAsync (File.ReadAllBytes (path));
yield return request;
if (request == null) yield break;
AssetBundle ab = request.assetBundle;
var go = ab.LoadAsset<GameObject> ("Cube");
Instantiate (go);
}
LoadFromMemory
void CreateAsset () {
var path = "AssetBundles/test/cube.unity3d";
AssetBundle ab = AssetBundle.LoadFromMemory (File.ReadAllBytes (path));
if (!ab) return;
var go = ab.LoadAsset<GameObject> ("Cube");
Instantiate (go);
}
LoadFromFileAsync
IEnumerator CreateAsset () {
var path = "AssetBundles/test/cube.unity3d";
AssetBundleCreateRequest request = AssetBundle.LoadFromFileAsync (path);
yield return request;
if (!request.assetBundle) yield break;
var ab = request.assetBundle;
var go = ab.LoadAsset<GameObject> ("Cube");
Instantiate(go);
}
LoadFromFile
//加载单个
AssetBundle ab = AssetBundle.LoadFromFile ("AssetBundles/test/cube.unity3d");
var go = ab.LoadAsset<GameObject> ("Cube");
Instantiate (go);
//加载多个
AssetBundle ab = AssetBundle.LoadFromFile ("AssetBundles/test/cube.unity3d");
Object[] objs = ab.LoadAllAssets ();
foreach (var item in objs) {
Instantiate (item);
}
- 通过UnityWebRequest加载(此方法客户端服务端都适用)
UnityWebRequest.GetAssetBundle
:获取ab资源,有一个返回资源的实例函数SendWebRequest
用来下载资源DownloadHandlerAssetBundle.GetContent
得到ab资源
IEnumerator LoadAsset () {
string path = @"";//这里ab资源路径,可为本地,也可以是服务端
UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle (path);
yield return request.SendWebRequest ();
while (request.isHttpError)
yield return null;
while (!request.isDone)
yield return null;
//第一种
//var ab = DownloadHandlerAssetBundle.GetContent (request);
//第二种 两种都可行
var ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
var go = ab.LoadAsset<GameObject> ("Cube");
Instantiate (go);
}
所有资源加载实例化后都需要删除内存中的AssetBundle资源镜像
- AssetBundle释放
函数名 | 作用 |
---|---|
Unload(false) | 仅释放内存镜像即本身 |
Unload(true) | 释放内存镜像以及从它加载的assets |
UnloadAllAssetBundles (false) | 释放所有内存镜像 |
UnloadAllAssetBundles (true) | 释放所有内存镜像以及从它加载的assets |
Resources.UnloadUnusedAssets() | 仅释放没有引用的Assets |
最后
关于AssetBundle更详细的介绍可参考以下文章
https://www.cnblogs.com/tekkaman/p/4040081.html
https://blog.youkuaiyun.com/lizhenxiqnmlgb/article/details/80433752
https://blog.youkuaiyun.com/llj1985/article/details/51314384
学习笔记,仅供参考,如有不正,欢迎指正