原文链接:(7条消息) 更方便地打包AB包(自动标记工具)(全手打详细解释)_AT巡礼的博客-CSDN博客
我直接复制原博的代码,发现有几处勘误(真是全手打的大佬,可能不在编辑器里编辑的),于是改了一下:
using System;
using System.IO;
using UnityEditor;
using UnityEngine;
public class AssetBundlesEditor
{
//写一个静态的启动内容的方法
[MenuItem("AssetsBundle/Set AssetBundle Lables")]
public static void Assetbundleseditor()
{
//第一步我们可以清空所有没有使用过的AB包的名字(如果你没不懂可以忽略这条,)
AssetDatabase.RemoveUnusedAssetBundleNames();
//AssetDatabase.RemoveAssetBundleName("scene/prefab",true);
//第二步,获取的们存取资源的路径的一级文件夹,类似Resource的这种资源根文件夹,当然打AB包的资源不能放在Resource里面
string ResPath = "D:/UnityProjects/Dynamic_HealthAssessment/Assets/HealthAssessment/HA_Models/Prefabs";
//获取路径之后,把路径的文件夹实例化(Dir就相当于Res,这样能明白了嘛)
DirectoryInfo Dir = new DirectoryInfo(ResPath);
//获取该文件夹下的所有文件系统(文件系统指 文件还有文件夹)(DirSons就相当于Res里所有的文件系统,这样能明白了嘛)
DirectoryInfo[] DirSons = Dir.GetDirectories(); //这里是二级文件夹
//第三步,遍历Res文件夹里面的子文件夹的所有文件系统,例如Res/Sence1 Res/Sence2
foreach (FileSystemInfo filesysinfo in DirSons) //为什么这里要用FileSystemInfo,最下面有文字注释
{
//获取Res的子文件系统的路径(由于DirctoryInfo要通过路径才能获取文件系统)
String SonsPath = ResPath + "/" + filesysinfo.Name;
//获取文件系统
DirectoryInfo Dinfo = new DirectoryInfo(SonsPath);
//判断DInfo是否为空
if (Dinfo == null)
{
return;
}
else
{
//D:\UnityProjects\Dynamic_HealthAssessment\Assets\HealthAssessment\HA_Models\Prefabs\ForHands
//这是我们搜到的Dinfo路径 获取“\”最后一个的文件系统的名字
//获取该名字是为了等下给文件打AB包时,设置AB包名用的
#region 不明修改
int index = Dinfo.FullName.LastIndexOf(@"\");
string lastName = Dinfo.FullName.Substring(index + 1);//通过这个可以获取当前我们搜到的文件系统的名称
#endregion
//写一个方法。用于修改文件的AB包名称,如果是文件夹还得继续遍历
AssetBundleFilesystemInfo(Dinfo, lastName);
}
}
}
//第一个参数是文件系统,第二个参数是ab包的路径名称
public static void AssetBundleFilesystemInfo(FileSystemInfo fileSystemInfo, string AbPathName)
{
//判断文件系统是否为空
if (!fileSystemInfo.Exists)
{
Debug.LogError("该文件夹为空" + fileSystemInfo.FullName + "is null");
return;
}
//如果继续则是找到了文件系统
//获取该文件系统(实例化,这是二级文件夹下的文件系统)
DirectoryInfo Dire_02 = new DirectoryInfo(fileSystemInfo.FullName);
//遍历二级文件夹 下所有的文件系统
foreach (FileSystemInfo sysinfo_03 in Dire_02.GetFileSystemInfos())
{
//不知道是文件还是文件夹,强转试试
FileInfo fileinfo = sysinfo_03 as FileInfo;
if (fileinfo == null)//表示强转失败,该文件系统是文件夹而不是文件
{
//继续遍历,使用递归方法
//int index = sysinfo_03.FullName.LastIndexOf(@"\");
//string lastName = sysinfo_03.FullName.Substring(index + 1);//通过这个可以获取当前我们搜到的文件系统的名称
AssetBundleFilesystemInfo(sysinfo_03, AbPathName);
}
else
{
//强转成功,是文件,写一个方法开始标记AB包的名称,
SetAssetBundleName(fileinfo, AbPathName);
}
}
}
public static void SetAssetBundleName(FileInfo fileinfo, string AbPathName)
{
if (fileinfo.Extension == ".meta")//这个.meta文件是属于系统自动生成的备份文件,我们不需要,所以写个方法排除掉
{
return;
}
//接下来就是我们找到的需要的文件了
//找到文件要给文件设置包名,那么我们需要获取包名,例如图片上的Sence/Mode这种路径就是包名
//写个方法,获取包名
string ABname = GetBundlePath(fileinfo, AbPathName);
//获取到了包名之后,我们就需要开始将文件资源进行设置包名
//获取文件资源,此时我们只需要Asset后面的路径
int index = fileinfo.FullName.IndexOf("Assets"); //从头开始计数看到第几位会遇到这个字符串,返回数值
string path_last = fileinfo.FullName.Substring(index); //获得Assets\Res\Sence\Mode\Cube.prefab
AssetImporter assetImporter = AssetImporter.GetAtPath(path_last);//通过该API获取路径资源(该路径是unity项目内部的路径)
assetImporter.assetBundleName = ABname;//设置包名成功
//还有一步,设置后缀,检测该文件资源是不是场景
if (fileinfo.Extension == ".unity")//文件名后缀是不是unity
{
//是场景文件
assetImporter.assetBundleVariant = "u3d";
}
else
assetImporter.assetBundleVariant = "assetbundle";
//自动标记工具完成!
}
public static string GetBundlePath(FileInfo fileinfo, string AbPathName)
{
string WindowsPath = fileinfo.FullName;
//我们可以获取到全路径例如F:\WorkScript\New Unity Project\Assets\Res\Sence\Mode\Cube.prefab
//你可以发现这路径是反斜杠,因为Windows的路径就是用反斜杠的
//把他转成Unity可以识别的路径
string UnityPath = WindowsPath.Replace(@"\", "/"); //替换斜杠
//然后这个全路径我们却不用全要,我们只要例如Sence\Mode这个,即第二文件夹/第三文件夹(或者第二文件夹/)
//而Sence这个二级文件夹的名字就是AbPathName
//那么就需要获取三级文件夹的名称的,当然如果是三级文件,那就只要获取二级文件夹的名称
int Index = UnityPath.IndexOf(AbPathName) + AbPathName.Length;
string SenceAfter = UnityPath.Substring(Index+1); //可以获得Mode\Cube.prefab,这是个example,也可能获取的是其他
//如果Sence后面还有/表示有三级文件夹,如果没有那么就是三级文件
if (SenceAfter.Contains("/"))
{
//有三级文件夹,对路径按/为标记进行切割
string[] temp = SenceAfter.Split('/');
return AbPathName + "/" + temp[0]; //我这个只写到0,例如这条返回的可能是Sence/Mode,即可能不是Mode而是None,你可以扩展
}
else
{
return AbPathName;//这条返回的是Sence
}
}
}