AssetBundle是一种资源管理机制
游戏更新的方式:
小版本更新:资源更新(图片、音频、预制体等)和配置文件更新
大版本更新:更新的是活动、新的玩法、系统模块 等;主要用于更新代码,也可以用于更新资源
资源打包机制:
一些文件:音频、图片、配置文件或者Lua文件想要加载到已经安装的安装包里,只能通过 资源打包机制 进行加载
加载过程:将所有unity可以识别的资源类型 都理解为AssetBundle(资源包),加载之后如何使用,是逻辑层面的内容
注意:
AssetBundle 可以包含资源的全部依赖关系;预制体依赖材质球等
可压缩 跨文件 (预制体、二进制文件、图片等)
AssetBundle 是为了做资源更新存在的
使用流程:
打包
using UnityEditor;
using UnityEngine;
public class ABEditor : Editor
{
[MenuItem("AssetBundle/Build(Single)")]
static void BuildSingle()
{
BuildPipeline.BuildAssetBundles(
Application.streamingAssetsPath + "/",
BuildAssetBundleOptions.None,
BuildTarget.StandaloneWindows
);
AssetDatabase.Refresh();
}
[MenuItem("AssetBundle/Build(Collection)")]
static void BuildAll()
{
// 对当前选中的这些物体 进行整体打包
AssetBundleBuild[] builds = new AssetBundleBuild[1];
builds[0].assetBundleName = "allBundles";
Object[] selects = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets /*强制包含 整个资源 及其 对应的依赖资源*/);
string[] allAssetPaths = new string[selects.Length];
for (int i = 0; i < allAssetPaths.Length; i++)
{
allAssetPaths[i] = AssetDatabase.GetAssetPath(selects[i]);
}
builds[0].assetNames = allAssetPaths;
BuildPipeline.BuildAssetBundles(
Application.streamingAssetsPath + "/",
builds,
BuildAssetBundleOptions.None,
BuildTarget.StandaloneWindows
);
AssetDatabase.Refresh();
}
}
BuildAssetBundleOptions
1. None:构建AssetBundle没有任何特殊的选项;
2. UncompressedAssetBundle:不进行数据压缩。没有压缩/解压的过程,AssetBundle的发布和加载会更快,但是AssetBundle也会更大,导致下载速度变慢;
3. CollectDependencies:包括所有依赖关系的资源 (AssetBundle中所有类型的hash);
4. DisableWriteTypeTree:在AssetBundle中不包含类型信息(TypeTree)。Web平台上不能使用该选项;
5. DeterministicAssetBundle:使每个Object具有唯一不变的hash ID,使用ID可避免资源
改名、移动位置等导致重新导出。 可用于增量式发布AssetBundle;
6. ForceRebuildAssetBundle:强制重新Build所有的AssetBundle;
7. IgnoreTypeTreeChanges:忽略TypeTree的变化,不能与DisbaleTypeTree同时使用。
8. AppendHashToAssetBundleName:附加Hash到AssetBundle名称中。
9. ChunkBasedCompression:使用LZ4压缩算法来Build AssetBundle。默认LZMA压 缩。
10. StrictMode:如果发布过程中有任何错误报告就不允许发布成功。
11. DryRunBuild:获得打包一个AssetBundle的AssetBundleManifest,AssetBundleManifest对象包含有效AssetBundle依赖性和散列。但是不实际创建AssetBundle。
12. DisableLoadAssetByFileName:不允许AB包通过文件名加载资源。
13. DisableLoadAssetByFileNameWithExtension:禁用通过使用扩展名加载AssetBundle。
LZ4:相对 LZMA 压缩比更低,所以打包后 包体 会更大点,运行时 解压更快 且没有额外的内存消耗
LZMA:相对LZ4压缩更高,所以包体更小,运行时 解压速度 慢 且 有额外的内存消耗
加载
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LoadABTest : MonoBehaviour
{
private void OnGUI()
{
if (GUILayout.Button("单独加载Cube"))
{
StartCoroutine(LoadAssetBundleSingle("cube"));
}
if (GUILayout.Button("整体加载"))
{
StartCoroutine(LoadAssetBundleAll());
}
if (GUILayout.Button("LoadByCache"))
{
StartCoroutine(LoadAssetBundleByCacheOrDownload("sphere"));
}
}
IEnumerator LoadAssetBundleSingle(string assetName)
{
WWW www = new WWW(Application.streamingAssetsPath + "/" + assetName);
yield return www;
string[] assetBundles = www.assetBundle.GetAllAssetNames();
Instantiate(www.assetBundle.LoadAsset(assetBundles[0]));
// www.assetBundle.Unload(true);
}
IEnumerator LoadAssetBundleAll()
{
WWW www = new WWW(Application.streamingAssetsPath + "/allbundles");
yield return www;
string[] assetBundles = www.assetBundle.GetAllAssetNames();
foreach (string asset in assetBundles)
{
Instantiate(www.assetBundle.LoadAsset(asset));
}
}
IEnumerator LoadAssetBundleByCacheOrDownload(string name)
{
Caching.ClearCache();
WWW www = WWW.LoadFromCacheOrDownload(Application.streamingAssetsPath + "/" + name, 2);
yield return www;
string[] assetBundles = www.assetBundle.GetAllAssetNames();
Instantiate(www.assetBundle.LoadAsset(assetBundles[0]));
}
}
新版加载方式
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
using Object = System.Object;
public class LoadAssetBundle : MonoBehaviour
{
private void OnGUI()
{
if (GUILayout.Button("加载Cube"))
{
StartCoroutine(LoadAssetBundleSingle("cube"));
}
if (GUILayout.Button("加载整体"))
{
StartCoroutine(LoadAssetBundleAll());
}
}
IEnumerator LoadAssetBundleSingle(string assetName)
{
UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle("http://cdn.shongfei.top/test/cube");
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.ConnectionError ||
request.result == UnityWebRequest.Result.ProtocolError)
{
Debug.LogError(request.error);
}
print(request);
AssetBundle ab = (request.downloadHandler as DownloadHandlerAssetBundle)?.assetBundle;
print(ab);
// AssetBundle bundle = AssetBundle.LoadFromFile();
if (ab != null)
{
GameObject obj = ab.LoadAsset<GameObject>(assetName);
Instantiate(obj);
}
}
IEnumerator LoadAssetBundleAll()
{
AssetBundle bundle = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/allbundles");
yield return bundle;
Object[] bundles = bundle.LoadAllAssets();
foreach (GameObject bun in bundles)
{
Instantiate(bun);
}
}
}
卸载
AssetBundle 下载的资源(不管是从网络上 or 本地文件中)存储 在内存的文件镜像区域中
当使用Load去加载的时候,将 文件镜像内存 区域中的信息加载到 缓存区域(和Resources.Load加载资源属于同一个区域)
通过实例化的方法克隆出对象,会加载到另一块内存(实际内存),也就是说可以在场景视图中看到的对象
如果实例化出来的对象,使用Destroy来卸载释放
通过Resources.Load所加载的资源,需要通过Resources.UnLoadAssets和UnLoadUnsedAsset来卸载
AssetBundle.UnLoad卸载资源包:
- false 卸载的是文件内存 镜像区域,不会影响之前加载的资源的使用
- true 卸载的内存 镜像 和 通过Load加载的资源(缓存区)