- 使用代码打包AssetBundle
1.使用UnityEditor中的BuildPipeline.BuildAssetBundles方法,要确保保存的文件夹存在
2.注意事项:脚本要放在Assets/UnityEditor路径下,否则运行会报错
或者脚本放在其他文件夹下,可以这样:
#if UNITY_EDITOR
//用到UnityEditor命名空间下的代码
#endif
3.BuildPipeline.BuildAssetBundles(dir, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);
dir:AssetBundle要保存的路径
BuildAssetBundleOptions:build选型
BuildAssetBundleOptions.None:使用LZMA算法压缩,压缩的包更小,但是加载时间更长。使用之前需要整体解压。一旦被解压,这个包会使用LZ4重新压缩。使用资源的时候不需要整体解压。在下载的时候可以使用LZMA算法,一旦它被下载了之后,它会使用LZ4算法保存到本地上。
BuildAssetBundleOptions.UncompressedAssetBundle:不压缩,包大,加载快
BuildAssetBundleOptions.ChunkBasedCompression:使用LZ4压缩,压缩率没有LZMA高,但是我们可以加载指定资源而不用解压全部。
注意使用LZ4压缩,可以获得可以跟不压缩想媲美的加载速度,而且比不压缩文件要小。
BuildTarget:选择build出来的AssetBundle包要使用的平台
using System.IO; using UnityEditor; public class CreateAssetBundles { [MenuItem("Assets/Build AssetBundles")] static void BuildAllAssetBundles() { string dir = "AssetBundles"; if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } BuildPipeline.BuildAssetBundles(dir, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64); } }
以下是三种资源build的方式:
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;//改变添加unity编辑器类
public class AssetBundleTool
{
[MenuItem("Tools/AssetBundle/AllBundle")]
public static void AllBundle()
{
Debug.Log("启动所有的打包");
BuildPipeline.BuildAssetBundles(Application.dataPath + "/AssetsBundle", BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.StandaloneWindows64);
}
[MenuItem("Tools/AssetBundle/SingleBundle")]
public static void SingleBundle()
{
Debug.Log("启动打包");
AssetBundleBuild build = new AssetBundleBuild();
build.assetBundleName = "prefabs";
build.assetBundleVariant = "img";
build.assetNames = new string[] { "Assets/Resources/Image/img" };
AssetBundleBuild[] builds = new AssetBundleBuild[1] { build };
BuildPipeline.BuildAssetBundles(Application.dataPath + "/AssetsBundle", builds, BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.StandaloneWindows64);
}
[MenuItem("Tools/AssetBundle/SelectBundle2")]
public static void SelectBundle2()
{
Dictionary<string, AssetBundleBuild> assets = new Dictionary<string, AssetBundleBuild>();
//获取选择的资源 DeepAssets:获取所有文件夹及其子文件夹的资源
Object[] assetObjs = Selection.GetFiltered<Object>(SelectionMode.DeepAssets);
Debug.Log("资源的数量为:" + assetObjs.Length);
for (int i = 0; i < assetObjs.Length; i++)
{
string path = AssetDatabase.GetAssetPath(assetObjs[i]);
string assetName = AssetImporter.GetAtPath(path).assetBundleName;
string assetVariant = AssetImporter.GetAtPath(path).assetBundleVariant;
Debug.Log(path + "," + assetName + "," + assetVariant);
string key = assetName + "." + assetVariant;
if (assets.ContainsKey(key))
{
//更新
AssetBundleBuild build = assets[key];
string[] assetNames = build.assetNames;
string[] newAssetNames = new string[assetNames.Length + 1];
ArrayUtility.AddRange<string>(ref newAssetNames, assetNames);
newAssetNames[assetNames.Length] = path;
build.assetNames = newAssetNames;
assets[key] = build;
}
else
{
if (key != null && key != "" && key.Length > 1)
{
AssetBundleBuild build = new AssetBundleBuild();
build.assetBundleName = assetName;
build.assetBundleVariant = assetVariant;
build.assetNames = new string[1] { path };
assets.Add(key, build);
}
else
{
key = path.Substring(path.LastIndexOf(".") + 1);
if (assets.ContainsKey(key))
{
//更新
AssetBundleBuild build = assets[key];
string[] assetNames = build.assetNames;
string[] newAssetNames = new string[assetNames.Length + 1];
ArrayUtility.AddRange<string>(ref newAssetNames, assetNames);
newAssetNames[assetNames.Length] = path;
build.assetNames = newAssetNames;
assets[key] = build;
}
else
{
AssetBundleBuild build = new AssetBundleBuild();
//build.assetBundleName = assetName;
//build.assetBundleVariant = assetVariant;
build.assetBundleName = key;
build.assetNames = new string[1] { path };
assets.Add(key, build);
}
}
}
}
AssetBundleBuild[] builds = new AssetBundleBuild[assets.Count];
assets.Values.CopyTo(builds, 0);
Debug.Log(builds.Length);
BuildPipeline.BuildAssetBundles(Application.dataPath + "/AssetsBundle", builds, BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.StandaloneWindows64);
}
[MenuItem("Tools/AssetBundle/SelectBundle")]
public static void SelectBundle()
{
Dictionary<string, AssetBundleBuild> assets = new Dictionary<string, AssetBundleBuild>();
//获取所有的鼠标选择的对象
//SelectionMode.DeepAssets:收集所有包括文件夹,Assets,子文件夹。
Object[] objList = Selection.GetFiltered<Object>(SelectionMode.DeepAssets);
Debug.Log(objList.Length);
for (var i = 0; i < objList.Length; i++)
{
//获取该对象的在资源文件夹中的相对路径
string path = AssetDatabase.GetAssetPath(objList[i]);
Debug.Log(path);
//通过路径返回资源设置好的资源包的名字AssetBundleName
string assetName = AssetImporter.GetAtPath(path).assetBundleName;
//返回该对象的assetBundleVariant;
string variant = AssetImporter.GetAtPath(path).assetBundleVariant;
string key = assetName + "." + variant;
//Debug.Log (key);
if (assets.ContainsKey(key))
{
//原基础更新
AssetBundleBuild build = assets[key];
build.assetNames = AppendChild(build.assetNames, path);
assets[key] = build;
}
else
{
if (key != null && key != "" && key.Length > 1)
{
Debug.Log("456");
AssetBundleBuild build = new AssetBundleBuild();
build.assetBundleName = assetName;
build.assetBundleVariant = variant;
build.assetNames = new string[] { path };
assets.Add(key, build);
}
else
{
key = path.Substring(path.LastIndexOf(".") + 1);
Debug.Log(key);
if (assets.ContainsKey(key))
{
//原基础更新
AssetBundleBuild build = assets[key];
build.assetNames = AppendChild(build.assetNames, path);
assets[key] = build;
}
else
{
AssetBundleBuild build = new AssetBundleBuild();
build.assetBundleName = key;
build.assetNames = new string[] { path };
assets.Add(key, build);
}
}
}
}
//启动打包
AssetBundleBuild[] crr = new AssetBundleBuild[assets.Count];
assets.Values.CopyTo(crr, 0);
Debug.Log(crr[0].assetBundleName);
BuildPipeline.BuildAssetBundles(Application.dataPath + "/AssetsBundle", crr, BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.StandaloneWindows64);
}
static string[] AppendChild(string[] arr, string value)
{
string[] brr = new string[arr.Length + 1];
for (var i = 0; i < arr.Length; i++)
{
brr[i] = arr[i];
}
brr[brr.Length - 1] = value;
return brr;
}
}
- AssetBundle的加载和使用
1.使用AssetBundle.LoadFromFile方法加载保存在文件夹中的AssetBundle
2.使用AssetBundle.LoadAsset方法取得prefab
3.AssetBundle ab2 = AssetBundle.LoadFromFile("AssetBundles/scene/share.unity3d");先获得共享包share.unity3d(包含prefab引用的材质),
否则prefab会丢失材质(material)
using UnityEngine;
public class LoadFromAssetBundle : MonoBehaviour {
void Start () {
AssetBundle ab2 = AssetBundle.LoadFromFile("AssetBundles/scene/share.unity3d");
AssetBundle ab = AssetBundle.LoadFromFile("AssetBundles/scene/cube.unity3d");
GameObject cubePrefab = ab.LoadAsset<GameObject>("CubeWall");
Instantiate(cubePrefab);
}
}
- 加载AssetBundle的方式
1.第一种加载AB的方式LoadFromMemoryAsync(异步),LoadFromMemory(同步)
using UnityEngine;
using System.IO;
using System.Collections;
public class LoadFromAssetBundle : MonoBehaviour {
IEnumerator Start () {
string path1 = "AssetBundles/scene/cube.unity3d";
string path2 = "AssetBundles/scene/share.unity3d";
#region 第一种加载AB的方式LoadFromMemoryAsync(异步),LoadFromMemory(同步)
AssetBundleCreateRequest request1 = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path1));
yield return request1;
AssetBundleCreateRequest request2 = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path2));
yield return request2;
AssetBundle ab1 = request1.assetBundle;
//LoadFromMemory(同步)
//AssetBundle ab1 = AssetBundle.LoadFromMemory(File.ReadAllBytes(path1));
//AssetBundle ab2 = AssetBundle.LoadFromMemory(File.ReadAllBytes(path2));
#endregion
//使用里面的资源
GameObject cubePrefab = ab1.LoadAsset<GameObject>("CubeWall");
Instantiate(cubePrefab);
}
}
2.第二种加载AB的方式LoadFromFile(同步),LoadFromFileAsync(异步)
using UnityEngine;
using System.IO;
using System.Collections;
public class LoadFromAssetBundle : MonoBehaviour {
IEnumerator Start () {
string path1 = "AssetBundles/scene/cube.unity3d";
string path2 = "AssetBundles/scene/share.unity3d";
#region 第二种加载AB的方式LoadFromFile(同步),LoadFromFileAsync(异步)
//AssetBundle ab1 = AssetBundle.LoadFromFile(path1);
//AssetBundle ab2 = AssetBundle.LoadFromFile(path2);
//LoadFromFileAsync(异步)
AssetBundleCreateRequest request1 = AssetBundle.LoadFromFileAsync(path1);
yield return request1;
AssetBundleCreateRequest request2 = AssetBundle.LoadFromFileAsync(path2);
yield return request2;
AssetBundle ab1 = request1.assetBundle;
#endregion
//使用里面的资源
GameObject cubePrefab = ab1.LoadAsset<GameObject>("CubeWall");
Instantiate(cubePrefab);
}
}
3.第三种加载AB的方式WWW.LoadFromCacheOrDownload(全路径)
注意:此方式将会被弃用,换成第四种方式UnityWebRequest
using UnityEngine;
using System.IO;
using System.Collections;
public class LoadFromAssetBundle : MonoBehaviour {
#region 第二种加载AB的方式LoadFromFile(同步),LoadFromFileAsync(异步)
//AssetBundle ab1 = AssetBundle.LoadFromFile(path1);
//AssetBundle ab2 = AssetBundle.LoadFromFile(path2);
//LoadFromFileAsync(异步)
//AssetBundleCreateRequest request1 = AssetBundle.LoadFromFileAsync(path1);
//yield return request1;
//AssetBundleCreateRequest request2 = AssetBundle.LoadFromFileAsync(path2);
//yield return request2;
//AssetBundle ab1 = request1.assetBundle;
#endregion
#region 第三种加载AB的方式WWW
while (Caching.ready == false)
{
yield return null;
}
WWW www = WWW.LoadFromCacheOrDownload(@"file://D:\Program Files (x86)\Unity3Documents\AssetBundle\AssetBundles\scene\cube.unity3d", 1);
WWW www2 = WWW.LoadFromCacheOrDownload(@"file://D:\Program Files (x86)\Unity3Documents\AssetBundle\AssetBundles\scene\share.unity3d", 1);
yield return www;
yield return www2;
if (!string.IsNullOrEmpty(www.error))
{
Debug.Log(www.error);
yield break;
}
AssetBundle ab1 = www.assetBundle;
#endregion
//使用里面的资源
GameObject cubePrefab = ab1.LoadAsset<GameObject>("CubeWall");
Instantiate(cubePrefab);
}
}
4.第四种加载AB的方式 UnityWebRequest.GetAssetBundle(使用命名空间using UnityEngine.Networking)
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
public class LoadFromAssetBundle : MonoBehaviour {
IEnumerator Start () {
#region 第四种加载AB的方式 UnityWebRequest.GetAssetBundle
string uri1 = @"http://ccop.cn/AssetBundles/scene/cube.unity3d";
UnityWebRequest request = UnityWebRequest.GetAssetBundle(uri1);
yield return request.Send();
string uri2 = @"http://ccop.cn/AssetBundles/scene/share.unity3d";
UnityWebRequest request2 = UnityWebRequest.GetAssetBundle(uri2);
yield return request2.Send();
//第一种方式获取AssetBundle
AssetBundle ab1 = DownloadHandlerAssetBundle.GetContent(request);
DownloadHandlerAssetBundle.GetContent(request2);
//第二种方式获取AssetBundle
//AssetBundle ab1 = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
//AssetBundle ab2 = (request2.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
#endregion
//使用里面的资源
GameObject cubePrefab = ab1.LoadAsset<GameObject>("CubeWall");
Instantiate(cubePrefab);
}
}
- 从AssetBundle中获取资源(AssetBundle的使用)
1.获取对象
GameObject gameObject = loadedAssetBundle.LoadAsset<GameObject>(assetName);
Unity.Object[] objectArray = loadedAssetBundle.LoadAllAssets();
2.加载Manifests文件可以处理资源的依赖
AssetBundle assetBundle = AssetBundle.LoadFromFile(manifestFilePath);
AssetBundleManifest manifest = assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
string[] dependencies = manifest.GetAllDependencies("assetBundle"); //Pass the name of the bundle you want the dependencies for.
foreach(string dependency in dependencies)
{
AssetBundle.LoadFromFile(Path.Combine(assetBundlePath, dependency));
}
- AssetBundle的卸载
卸载有两个方面:
1,减少内存使用
2,有可能导致丢失
所以什么时候去卸载资源
AssetBundle.Unload(true)卸载所有资源,即使有资源被使用着
(1,在关切切换、场景切换2,资源没被用的时候 调用)
AssetBundle.Unload(false)卸载所有没用被使用的资源
个别资源怎么卸载1,通过 Resources.UnloadUnusedAssets.2,场景切换的时候
后续边学习边更新。。。
(敬请期待)