打包脚本
这个打包脚本适用于做demo,脚本放在Editor目录下
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
public class BuildAB
{
[MenuItem("Tools/递归遍历文件夹下的资源并打包")]
public static void BuildDirectory()
{
//需要打包的文件夹路径
string path = Application.dataPath + "/Res";
List<string> list = new List<string>();
GetFilePath(path, ref list);
List<AssetBundleBuild> mult = new List<AssetBundleBuild>();
for (int i = 0; i < list.Count; i++)
{
string assetName = list[i].Replace(Application.dataPath, "Assets").Replace("\\", "/");
string bundleName = Path.GetFileNameWithoutExtension(assetName);
AssetBundleBuild ab = new AssetBundleBuild();
ab.assetBundleName = bundleName;
//assetNames记录bundle中所有资源的相对路径
ab.assetNames = new string[] { assetName };
mult.Add(ab);
Debug.Log($"{assetName} {bundleName}");
}
string targetPath = Application.streamingAssetsPath;
if (Directory.Exists(targetPath))
Directory.Delete(targetPath, true);
Directory.CreateDirectory(targetPath);
BuildPipeline.BuildAssetBundles(targetPath, mult.ToArray(),
BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.StandaloneWindows64);
AssetDatabase.Refresh();
}
[MenuItem("Tools/遍历文件夹下的资源,处理依赖并打包")]
public static void BuildDirectoryDependence()
{
string path = Application.dataPath + "/Res";
List<string> list = new List<string>();
GetFilePath(path, ref list);
//key 资源路径,value 引用计数
Dictionary<string, int> abDict = new Dictionary<string, int>();
for (int i = 0; i < list.Count; i++)
{
string assetName = list[i].Replace(Application.dataPath, "Assets").Replace("\\", "/");
//获取依赖资源,返回相对路径
string[] dependences = AssetDatabase.GetDependencies(assetName);
for(int j = 0; j < dependences.Length; ++j)
{
if (dependences[j].EndsWith(".cs"))
{
continue;
}
Debug.Log($"{assetName} 依赖 {j} => {dependences[j]}");
if (abDict.ContainsKey(dependences[j]))
{
abDict[dependences[j]]++;
}
else
{
abDict.Add(dependences[j], 1);
}
}
}
var enumerator = abDict.GetEnumerator();
List<AssetBundleBuild> mult = new List<AssetBundleBuild>();
while (enumerator.MoveNext())
{
string fileName = enumerator.Current.Key;
int refCount = enumerator.Current.Value;
string bundleName = Path.GetFileNameWithoutExtension(fileName);
if(refCount > 1)
{
//引用计数大于1的为公共资源,单独打包
bundleName = "common/" + bundleName;
}
AssetBundleBuild ab = new AssetBundleBuild();
ab.assetBundleName = bundleName;
//assetNames记录bundle中所有资源的相对路径
ab.assetNames = new string[] { fileName };
mult.Add(ab);
}
string targetPath = Application.streamingAssetsPath;
if (Directory.Exists(targetPath))
Directory.Delete(targetPath, true);
Directory.CreateDirectory(targetPath);
BuildPipeline.BuildAssetBundles(targetPath, mult.ToArray(),
BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.StandaloneWindows64);
AssetDatabase.Refresh();
}
/// <summary>
/// 递归获取所有文件路径
/// </summary>
public static void GetFilePath(string path, ref List<string> list)
{
string[] files = Directory.GetFiles(path);
for (int i = 0; i < files.Length; i++)
{
if (files[i].EndsWith(".cs") || files[i].EndsWith(".meta"))
{
continue;
}
list.Add(files[i]);
}
string[] dirs = Directory.GetDirectories(path);
for(int i = 0; i < dirs.Length; i++)
{
GetFilePath(dirs[i], ref list);
}
}
}
前面的选项不会处理依赖关系,公共资源会打进不同的bundle里
后面的选项会处理依赖资源,引用计数大于1的认为是公共资源,单独打包到common文件夹
加载脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LoadAB : MonoBehaviour
{
private AssetBundleManifest _manifest;
private List<string> _abList = new List<string>();
private Dictionary<string, GameObject> _assetDict = new Dictionary<string, GameObject>();
void Start()
{
LoadManifest();
LoadGameObject("cube");
}
void LoadManifest()
{
AssetBundle assetBundle = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/StreamingAssets");
_manifest = assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
}
private void LoadGameObject(string abName)
{
if (string.IsNullOrEmpty(abName))
return;
abName = abName.ToLower();
//先加载依赖资源
string[] dependens = _manifest.GetAllDependencies(abName);
for (int i = 0; i < dependens.Length; ++i)
{
if (!_abList.Contains(dependens[i]))
{
AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + dependens[i]);
_abList.Add(dependens[i]);
}
}
if (!_abList.Contains(abName))
{
AssetBundle ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + abName);
_abList.Add(abName);
_assetDict.Add(abName, ab.LoadAsset<GameObject>(abName));
}
if (_assetDict.ContainsKey(abName))
{
GameObject.Instantiate(_assetDict[abName]);
}
}
}
参考
untiy AssetBundle 依赖关系树