在开发过程中,其实很难兼顾到一边开发,一边在导入资源的时候又同时给资源设置Assetbundle名字及后缀,这里就需要用代码去批量处理,是分成小文件夹打包,在某些情况下,单个资源需要单独打成一个包。
需要用一个字典把要被打包的资源存起来
static Dictionary<string, AssetBundleBuild> maps = new Dictionary<string, AssetBundleBuild>();
下面方法中的AppConst.ExtName = “.unity3d”,一般打包采用".unity3d"为后缀名
目录打包
/// <summary>
/// 目录打包
/// </summary>
/// <param name="bundleName"> 打出来的Bundle的名字 </param>
/// <param name="pattern"> 匹配模式,打那种类型的文件到包里面 </param>
/// <param name="path"> 需要被打包的目录 </param>
/// <param name="isAll"></param>
static void AddBuildMap(string bundleName, string pattern, string path, bool isAll = false)
{
string[] files;
if (isAll)
{
files = Directory.GetFiles(path, pattern, SearchOption.AllDirectories);
}
else
{
files = Directory.GetFiles(path, pattern);
}
//这里是过滤掉.meta文件
files = files.Where(f => !f.EndsWith(".meta")).ToArray();
if (files.Length == 0) return;
for (int i = 0; i < files.Length; i++)
{
files[i] = files[i].Replace('\\', '/');
}
AssetBundleBuild abb = new AssetBundleBuild();
abb.assetBundleName = bundleName.ToLower(); //设置包名
abb.assetNames = files;
abb.assetBundleVariant = AppConst.ExtName.Replace(".", "");//设置后缀名
if (!maps.ContainsKey(abb.assetBundleName.ToLower()))
{
maps.Add(abb.assetBundleName, abb);
}
else
{
Debug.LogError("maps same key: " + abb.assetBundleName.ToLower() + " build: " + abb);
EditorUtility.ClearProgressBar();
}
}
单个文件打包
/// <summary>
/// 单文件打包
/// </summary>
/// <param name="FloderName"> 打出来的Bundle所放的目录文件夹 </param>
/// <param name="pattern">匹配模式,打那种类型的文件到包里面</param>
/// <param name="path">需要被打包的目录</param>
static void AddBuildMapOneFile(string FloderName, string pattern, string path)
{
string[] files = Directory.GetFiles(path, pattern, SearchOption.AllDirectories);
if (files.Length == 0) return;
for (int i = 0; i < files.Length; i++)
{
string fileName = Path.GetFileNameWithoutExtension(files[i]);
files[i] = files[i].Replace('\\', '/');
AssetBundleBuild build = new AssetBundleBuild();
build.assetBundleName = (FloderName + fileName).ToLower(); //设置包名
build.assetNames = new string[] { files[i] };
build.assetBundleVariant = AppConst.ExtName.Replace(".", "");//设置后缀名
if (!maps.ContainsKey(build.assetBundleName.ToLower()))
{
maps.Add(build.assetBundleName.ToLower(), build);
}
else
{
UnityEngine.Debug.LogError("maps same key: " + build.assetBundleName.ToLower() + " build: " + build);
EditorUtility.ClearProgressBar();
}
}
}
后续在使用的过程中,调用上面的某一个方法,就能设置好需要被导报的目录下的所有资源名字,需要注意的是,最好把大文件与小文件分开,小文件分文件夹打包就行,大文件可以选择单个打包,这样后面方便加载
使用示例
假设现在要打包Sprite是目录下的资源,采用文件夹打包的方式
/// <summary>
/// 处理精灵打包(每个小文件夹里面的精灵打成一个bundle)
/// </summary>
static void BuildSpriteBundle()
{
string dirPath = AppConst.GetSAurl();// AppConst.GetSAurl() 就是 Build/My_AssetBundle路径
// 要被打包的文件夹
string[] dirs = Directory.GetDirectories("Assets/GameAssets/UI/Sprites/");
for (int i = 0; i < dirs.Length; i++)
{
string[] aFile = dirs[i].Split('/');
string dirName = aFile[aFile.Length - 1]; //这里就是拿到了上面截图的Icon文件夹名字
string resPath = dirPath + "/sprite/";
if (!Directory.Exists(resPath))
Directory.CreateDirectory(resPath);
AddBuildMap("sprite/" + dirName, "*.png", "Assets/GameAssets/UI/Sprites/" + dirName + "/");
}
}
测试打包Sprite精灵文件夹
[MenuItem("MyTools/FloderBundle")]
static void FloderBundle()
{
BuildSpriteBundle();
string resPath = AppConst.GetSAurl();
Directory.Delete(resPath, true);
if (Directory.Exists(resPath) == false)
{
Directory.CreateDirectory(resPath);
}
//string resPath = Application.streamingAssetsPath;
EditorUtility.DisplayProgressBar("BuildResource", "BuildAssetBundles", 0.1f);
AssetBundleManifest manifest = BuildPipeline.BuildAssetBundles(resPath, maps.Values.ToArray(), BuildAssetBundleOptions.None, BuildTarget.Android);
CreateFilesTxt(manifest);
EditorUtility.ClearProgressBar();
EditorUtility.DisplayDialog("AssetsbundleMsg:", "打包完成!", "确定");
System.Diagnostics.Process.Start(resPath);
}
等待”打包成功“的窗口弹出,然后打开Build/My_AssetBundle可看到
打开manifast文件可以查看包里所包含的图片以及依赖,因为打包的是图片目录,所以这里看到的
依赖Dependencies是一个空值
这就是一个简单的使用代码批量设置包名以及后缀,实现目录打包的过程