构建AB包

本文介绍了一个Unity编辑器脚本,用于自动设置AssetBundle标签,简化资源管理和打包流程。脚本能够遍历指定目录下的所有资源文件,并为它们设置合适的AssetBundle名称。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Security.Cryptography;
using System.Text;

/// <summary>
/// AssetBundle编辑
/// </summary>
public class AssetBundleEditor
{
#region 自动做标记

//思路
//1.找到资源保存的文件夹
//2.遍历里面的每个场景文件夹
//3.遍历场景文件夹里的所有文件系统
//4.如果访问的是文件夹:再继续访问里面的所有文件系统,直到找到 文件 (递归)
//5.找到文件 就要修改他的 assetbundle labels
//6.用 AssetImporter 类 修改名称和后缀
//7.保存对应的 文件夹名 和 具体路径

[MenuItem("AssetBundle/Set AssetBundle Labels")]
public static void SetAssetBundleLabels()
{
//移除所有没有使用的标记
AssetDatabase.RemoveUnusedAssetBundleNames();

//1.找到资源保存的文件夹
string assetDirectory = Application.dataPath + "/Res";
//Debug.Log(assetDirectory);

DirectoryInfo directoryInfo = new DirectoryInfo(assetDirectory);
DirectoryInfo[] sceneDirectories = directoryInfo.GetDirectories();
//2.遍历里面的每个场景文件夹
foreach (DirectoryInfo tmpDirectoryInfo in sceneDirectories)
{
string sceneDirectory = assetDirectory + "/" + tmpDirectoryInfo.Name;
DirectoryInfo sceneDirectoryInfo = new DirectoryInfo(sceneDirectory);
//错误检测
if (sceneDirectoryInfo == null)
{
Debug.LogError(sceneDirectory + " 不存在!");
return;
}
else
{
Dictionary<string, string> namePahtDict = new Dictionary<string, string>();

//3.遍历场景文件夹里的所有文件系统
//sceneDirectory
//C:\Users\张晋枭\Documents\ABLesson\Assets\AssetBundles\Res\Scene1

//C:/Users/张晋枭/Documents/ABLesson/Assets/AssetBundles/Res/Scene1
int index = sceneDirectory.LastIndexOf("/");
string sceneName = sceneDirectory.Substring(index + 1);
onSceneFileSystemInfo(sceneDirectoryInfo, sceneName, namePahtDict);

onWriteConfig(sceneName, namePahtDict);
}
}

AssetDatabase.Refresh();

Debug.Log("设置成功");
}

/// <summary>
/// 记录配置文件
/// </summary>
private static void onWriteConfig(string sceneName, Dictionary<string, string> namePathDict)
{
string path = PathUtil.GetAssetBundleOutPath() + "/" + sceneName + "Record.txt";
// Debug.Log(path);

using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
{
//写二进制
using (StreamWriter sw = new StreamWriter(fs))
{
sw.WriteLine(namePathDict.Count);

foreach (KeyValuePair<string, string> kv in namePathDict)
sw.WriteLine(kv.Key + " " + kv.Value);
}
}

}

/// <summary>
/// 遍历场景文件夹里的所有文件系统
/// </summary>
private static void onSceneFileSystemInfo(FileSystemInfo fileSystemInfo, string sceneName, Dictionary<string, string> namePahtDict)
{
if (!fileSystemInfo.Exists)
{
Debug.LogError(fileSystemInfo.FullName + " 不存在!");
return;
}

DirectoryInfo directoryInfo = fileSystemInfo as DirectoryInfo;
FileSystemInfo[] fileSystemInfos = directoryInfo.GetFileSystemInfos();
foreach (var tmpFileSystemInfo in fileSystemInfos)
{
FileInfo fileInfo = tmpFileSystemInfo as FileInfo;
if (fileInfo == null)
{
//代表强转失败,不是文件 就是文件夹
//如果访问的是文件夹:再继续访问里面的所有文件系统,直到找到 文件 (递归)
onSceneFileSystemInfo(tmpFileSystemInfo, sceneName, namePahtDict);
}
else
{
//就是文件
//5.找到文件 就要修改他的 assetbundle labels
setLabels(fileInfo, sceneName, namePahtDict);
}
}
}

/// <summary>
/// 修改资源文件的 assetbundle labels
/// </summary>
private static void setLabels(FileInfo fileInfo, string sceneName, Dictionary<string, string> namePahtDict)
{
//对unity自身生成的meta文件 无视它
if (fileInfo.Extension == ".meta")
return;

string bundleName = getBundleName(fileInfo, sceneName);
//C:\Users\张晋枭\Documents\ABLesson\Assets\Res\Scene1\Buildings\Folder\Building4.prefab
int index = fileInfo.FullName.IndexOf("Assets");
//Assets\Res\Scene1\Buildings\Folder\Building4.prefab
string assetPath = fileInfo.FullName.Substring(index);

AssetImporter assetImporter = AssetImporter.GetAtPath(assetPath);
//用 AssetImporter 类 修改名称和后缀
assetImporter.assetBundleName = bundleName.ToLower();
if (fileInfo.Extension == ".unity")
assetImporter.assetBundleVariant = "u3d";
else
assetImporter.assetBundleVariant = "assetbundle";

string folderName = "";
//添加到字典里
if (bundleName.Contains("/"))
folderName = bundleName.Split('/')[1];
else
folderName = bundleName;

string bundlePath = assetImporter.assetBundleName + "." + assetImporter.assetBundleVariant;
if (!namePahtDict.ContainsKey(folderName))
namePahtDict.Add(folderName, bundlePath);
}


/// <summary>
/// 获取包名
/// </summary>
private static string getBundleName(FileInfo fileInfo, string sceneName)
{
string windowsPath = fileInfo.FullName;//C:\Users\张晋枭\Documents\ABLesson\Assets\Res\Scene1\Buildings\Folder\Building4.prefab
//转换成unity可识别的路径
string unityPath = windowsPath.Replace(@"\", "/");

//C:/Users/张晋枭/Documents/ABLesson/Assets/Res/Scene1 /Buildings/Folder/Building4.prefab
//C: \Users\张晋枭\Documents\ABLesson\Assets\Res\Scene1\Scene1.unity
int index = unityPath.IndexOf(sceneName) + sceneName.Length;

string bundlePath = unityPath.Substring(index + 1);

if (bundlePath.Contains("/"))
{
//Buildings/Folder/Folder/Folder/Folder/Folder/Building4.prefab
string[] tmp = bundlePath.Split('/');
return sceneName + "/" + tmp[0];
}
else
{
//Scene1.unity
return sceneName;
}
}

#endregion

#region 打包

[MenuItem("AssetBundle/Build AssetBundles")]
static void BuildAllAssetBundles()
{
string outPath = PathUtil.GetAssetBundleOutPath();

BuildPipeline.BuildAssetBundles(outPath, 0, BuildTarget.StandaloneWindows64);
}


#endregion

#region 一键删除

[MenuItem("AssetBundle/Delete All")]
static void DeleteAssetBundle()
{
string outPath = PathUtil.GetAssetBundleOutPath();

Directory.Delete(outPath, true);
File.Delete(outPath + ".meta");

AssetDatabase.Refresh();
}

#endregion




[MenuItem("Tools/Create Files")]
static void CreateFiles()
{
//C:/Users/Ahpily/Desktop/AB/Assets/StreamingAssets/Windows
string outPath = PathUtil.GetAssetBundleOutPath();
//校验文件的路径
string filePath = outPath + "/files.txt";
if (File.Exists(filePath))
File.Delete(filePath);

//遍历这个文件夹下面的所有文件
List<string> fileList = new List<string>();
listFiles(new DirectoryInfo(outPath), ref fileList);

FileStream fs = new FileStream(filePath, FileMode.CreateNew);
StreamWriter sw = new StreamWriter(fs);

for (int i = 0; i < fileList.Count; i++)
{
string file = fileList[i];
string ext = Path.GetExtension(file);
if (ext.EndsWith(".meta"))
continue;

//生成这个文件对应的md5值
string md5 = getFileMd5(file);
//scene1.assetbundle
string value = file.Replace(outPath + "/", string.Empty);
//写入到文件
sw.WriteLine(value + "|" + md5);
}

sw.Close();
fs.Close();

AssetDatabase.Refresh();
}

/// <summary>
/// 遍历文件夹下的所有文件
/// </summary>
/// <param name="fileSystemInfo">文件夹的路径</param>
/// <param name="fileList"></param>
static void listFiles(FileSystemInfo fileSystemInfo, ref List<string> fileList)
{
DirectoryInfo directoryInfo = fileSystemInfo as DirectoryInfo;
//获取所有的文件系统
FileSystemInfo[] infos = directoryInfo.GetFileSystemInfos();

foreach (var info in infos)
{
FileInfo fileInfo = info as FileInfo;
//如果是文件 就成功了
if (fileInfo != null)
{
fileList.Add(fileInfo.FullName.Replace("\\", "/"));
}
//如果是文件夹就不成功 null
else
{
//递归
listFiles(info, ref fileList);
}
}

}

/// <summary>
/// 获取文件的md5值
/// </summary>
/// <param name="filePath"></param>
static string getFileMd5(string filePath)
{
FileStream fs = new FileStream(filePath, FileMode.Open);
MD5 md5 = new MD5CryptoServiceProvider();

byte[] result = md5.ComputeHash(fs);
fs.Close();

StringBuilder sb = new StringBuilder();
for (int i = 0; i < result.Length; i++)
{
sb.Append(result[i].ToString("x2"));
}
return sb.ToString();
}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值