实例介绍
【实例截图】
【核心代码】
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Linq;
public class AssetbundlePackat
{
//把需要热更的Resources资源放入HotUpdate文件夹,如果需要默认读取resources/HotUpdate下的资源
//,请不要添加到LevelVersion.xml版本中,也不要生成ab包,等需要热更修改内容时,再包含进去版本中,并生成ab包
//注意:不要为了省时间,只打一个需要的ab包,需要整体重新打ab包,因为会生成ab依赖分析包
static string m_beginPath;
static string beginPath
{
get
{
if (string.IsNullOrEmpty(m_beginPath))
{
int index = Application.dataPath.LastIndexOf("Assets");
m_beginPath = Application.dataPath.Remove(index);
}
return m_beginPath;
}
}
#region 清除AssetBundle包名
[MenuItem("HotTools/ClearAbName")]
static void ClearABNames()
{
//清除旧的ab包名
EditorUtility.DisplayProgressBar("搜索ab包名", "进行中...", 0.2f);
string[] abnames = AssetDatabase.GetAllAssetBundleNames();
for(int i=0;i<abnames.Length;i )
{
EditorUtility.DisplayProgressBar("清除ab包名", abnames[i], (i 1f) / abnames.Length);
AssetDatabase.RemoveAssetBundleName(abnames[i], true);
}
EditorUtility.ClearProgressBar();
}
#endregion
#region 设置AssetBundle包名
const int ReferenceThreshold = 2;//大于阀值设置ab名字,不被包含,而被依赖
static int objDependencieCount = 0;//依赖计数
static Dictionary<string, bool> dicAtlasSetAbNameFlag = new Dictionary<string,bool>();//图集设置assetName标识
static Dictionary<string, Dictionary<string,bool>> dicObjRelyNum = new Dictionary<string, Dictionary<string,bool>>();//key=objPath value=依赖列表
static Dictionary<string, Dictionary<string,bool>> dicAtlasObjRelyNum = new Dictionary<string, Dictionary<string,bool>>();//key=packing Tag value=依赖列表
static void InitSetAssetBundle()
{
AssetDatabase.SaveAssets();
objDependencieCount = 0;
dicAtlasSetAbNameFlag.Clear();
dicObjRelyNum.Clear();
dicAtlasObjRelyNum.Clear();
dicSpritePackingTagList.Clear();
GetSpriteListAtPackingTag(Application.dataPath);
}
#region packing Tag sprite列表
static Dictionary<string, List<string>> dicSpritePackingTagList = new Dictionary<string, List<string>>();//packing Tag sprite列表
static void GetSpriteListAtPackingTag(string path)
{
string[] filePaths = Directory.GetFiles(path);
List<string> ignoreExtens = new List<string> { "", ".lua", ".cs", ".dll", ".json", ".mat", ".meta", ".DS_Store", ".text", ".xml", ".prefab", ".ab", ".mp4", ".mp3" };
for (int i=0;i<filePaths.Length;i )
{
string fp = filePaths[i];
string exten = Path.GetExtension(fp);
if (ignoreExtens.Contains(exten)) continue;
string relativePath = fp.Replace(Application.dataPath, "Assets");
EditorUtility.DisplayProgressBar("分析图集Sprite", relativePath, ((float)i) / filePaths.Length);
AssetImporter aImport = AssetImporter.GetAtPath(relativePath);
TextureImporter ti = aImport as TextureImporter;
if (ti != null && ti.textureType == TextureImporterType.Sprite)
{
ti.isReadable = false;
if (!dicSpritePackingTagList.ContainsKey(ti.spritePackingTag))
dicSpritePackingTagList.Add(ti.spritePackingTag, new List<string>());
dicSpritePackingTagList[ti.spritePackingTag].Add(relativePath);
}
}
string[] direPaths = Directory.GetDirectories(path);
foreach (var d in direPaths)
{
if (Path.GetDirectoryName(d) == "Editor") continue;
GetSpriteListAtPackingTag(d);
}
}
#endregion
/// <summary>
/// 热更新目录
/// </summary>
const string ScenesDirector = "/Scenes";
/// <summary>
/// 分析依赖
/// </summary>
static void AnalyzeRely()
{
InitSetAssetBundle();
DirectoryInfo dirinfo=null;
#region Resources文件夹下资源对象
string resourceHotDire = string.Format("{0}/Resources/{1}", Application.dataPath, HotDataContext.HotDirector);
//现在Resources文件夹找需要打ab的资源
if (Directory.Exists(resourceHotDire))
dirinfo = new DirectoryInfo(resourceHotDire);
else if (Directory.Exists(string.Format("{0}/{1}", Application.dataPath, HotDataContext.HotDirector)))
dirinfo = new DirectoryInfo(string.Format("{0}/{1}",Application.dataPath, HotDataContext.HotDirector));
if (dirinfo != null)
{
FileInfo[] fs = dirinfo.GetFiles("*.*", SearchOption.AllDirectories);
foreach (FileInfo f in fs)
{
string ext_name = Path.GetExtension(f.Name);
if (ext_name == ".meta" || ext_name == ".DS_Store") continue;
string path = f.FullName.Replace("\\", "/");
string relativalPath = path.Replace(Application.dataPath, "Assets");
ObjDependencie(string.Empty, relativalPath);
}
}
#endregion
#region Scenes文件
EditorBuildSettingsScene[] scenes = EditorBuildSettings.scenes;
if (Directory.Exists(Application.dataPath ScenesDirector))
{
dirinfo = new DirectoryInfo(Application.dataPath ScenesDirector);
FileInfo[] fs = dirinfo.GetFiles("*.unity", SearchOption.TopDirectoryOnly);
foreach (FileInfo f in fs)
{
string path = f.FullName.Replace("\\", "/");
string relativalPath = path.Replace(Application.dataPath, "Assets");
for (int i = 0; i < scenes.Length; i )
{
EditorBuildSettingsScene scene = scenes[i];
if (scene.path.Equals(relativalPath))
ObjDependencie(string.Empty, relativalPath);
}
}
}
#endregion
}
[MenuItem("HotTools/SetAbName")]
static void SetAssetBundleName()
{
//把图集建立启用Editor->Project Settings->Editor->Sprote Packer Mode Enabled
//清除旧的ab包名
//ClearABNames();
AnalyzeRely();//分析依赖
SetAbName();
}
static void SetAbName()
{
int curProgress = 0;
float totalProgress = dicObjRelyNum.Count dicAtlasObjRelyNum.Count;
foreach (string objPath in dicObjRelyNum.Keys)
{
EditorUtility.DisplayProgressBar("设置ab包名", objPath, curProgress / totalProgress);
if (!dicObjRelyNum[objPath].ContainsKey(string.Empty) && dicObjRelyNum[objPath].Count < ReferenceThreshold) continue;
string exten = Path.GetExtension(objPath);
string newExten = exten.Replace('.', '_');
string assetbundleName = objPath.Replace(exten, newExten);
assetbundleName = assetbundleName.Replace('/', '.');
AssetImporter aImport = AssetImporter.GetAtPath(objPath);
aImport.SetAssetBundleNameAndVariant(assetbundleName ".ab", string.Empty);
}
//图集
foreach (string packingTag in dicAtlasObjRelyNum.Keys)
{
EditorUtility.DisplayProgressBar("设置ab包名", packingTag, curProgress / totalProgress);
if (dicAtlasObjRelyNum[packingTag].Count < ReferenceThreshold) continue;
//if (dicAtlasObjRelyNum[packingTag] < Threshold) continue;
List<string> list = dicSpritePackingTagList[packingTag];
for (int i = 0; i < list.Count; i )
{
AssetImporter tempImport = AssetImporter.GetAtPath(list[i]);
tempImport.SetAssetBundleNameAndVariant(packingTag "_atlas" ".ab", string.Empty);// 图集格式:atlas
}
}
EditorUtility.ClearProgressBar();
AssetDatabase.SaveAssets();
}
static void ObjDependencie(string referenceObjPath,string objPath)
{
EditorUtility.DisplayProgressBar("正在分析依赖" objDependencieCount , objPath, 0);
AssetImporter aImport= AssetImporter.GetAtPath(objPath);
TextureImporter ti = aImport as TextureImporter;
if (ti != null && ti.textureType == TextureImporterType.Sprite)
{
if (!dicAtlasSetAbNameFlag.ContainsKey(ti.spritePackingTag))
{
dicAtlasSetAbNameFlag.Add(ti.spritePackingTag, true);
dicAtlasObjRelyNum.Add(ti.spritePackingTag, new Dictionary<string, bool>());
}
if(!dicAtlasObjRelyNum[ti.spritePackingTag].ContainsKey(referenceObjPath))dicAtlasObjRelyNum[ti.spritePackingTag].Add(referenceObjPath,true);
return;
}
if (!dicObjRelyNum.ContainsKey(objPath)) dicObjRelyNum.Add(objPath, new Dictionary<string, bool>());
if(!dicObjRelyNum[objPath].ContainsKey(referenceObjPath)) dicObjRelyNum[objPath].Add(referenceObjPath, true);
string[] relyPathArr = AssetDatabase.GetDependencies(objPath, false);
foreach (string relyObjPath in relyPathArr)
{
if (objPath == relyObjPath) continue;//原对象本身,不依赖自己
string exten = Path.GetExtension(relyObjPath);
if (exten == ".cs") continue;
if (exten == ".dll") continue;
ObjDependencie(objPath,relyObjPath);
}
}
#endregion
[MenuItem("HotTools/所选物体设置AbName")]
static void SelectObjectSetAbName()
{
ClearABNames();
InitSetAssetBundle();
List<string> relativalPathList = new List<string>();
EditorBuildSettingsScene[] scenes = EditorBuildSettings.scenes;
Object[] objs= Selection.objects;
foreach (var obj in objs)
{
string relativalPath= AssetDatabase.GetAssetPath(obj);
string path= beginPath AssetDatabase.GetAssetPath(obj);
bool resourceHot = relativalPath.IndexOf("Assets/Resources/" HotDataContext.HotDirector) == 0;
bool isScene = relativalPath.IndexOf("Assets/Scenes") == 0;
if (resourceHot || isScene)
{
if (Directory.Exists(path))
{
DirectoryInfo dirinfo = new DirectoryInfo(path);
FileInfo[] fs = dirinfo.GetFiles("*.*", SearchOption.AllDirectories);
foreach (FileInfo f in fs)
{
string ext_name = Path.GetExtension(f.Name);
if (ext_name == ".meta" || ext_name == ".DS_Store") continue;
string childRelativalPath = f.FullName.Replace("\\", "/").Replace(Application.dataPath, "Assets");
if (isScene)
{
if (childRelativalPath.IndexOf("Assets/Scenes/Fix/") != -1) continue;
for (int i = 0; i < scenes.Length; i )
{
EditorBuildSettingsScene scene = scenes[i];
if (scene.path.Equals(childRelativalPath) &&
!relativalPathList.Contains(childRelativalPath))
relativalPathList.Add(childRelativalPath);
}
}
else if (!relativalPathList.Contains(childRelativalPath))
relativalPathList.Add(childRelativalPath);
}
}
else if (File.Exists(path))
{
if (isScene)
{
if (relativalPath.IndexOf("Assets/Scenes/Fix/") != -1) continue;
for (int i = 0; i < scenes.Length; i )
{
EditorBuildSettingsScene scene = scenes[i];
if (scene.path.Equals(relativalPath)&&
!relativalPathList.Contains(relativalPath))
relativalPathList.Add(relativalPath);
}
}
else
{
if (!relativalPathList.Contains(relativalPath))
relativalPathList.Add(relativalPath);
}
}
}
}
foreach (var relativalPath in relativalPathList)
ObjDependencie(string.Empty, relativalPath);
SetAbName();
}
#region 建立AssetBundle
[MenuItem("HotTools/建立AB包(Android)")]
static void BuildAssetBundleAndroid()
{
BuildAssetBundle(BuildTarget.Android,false);
}
[MenuItem("HotTools/建立AB包(IOS)")]
static void BuildAssetBundleIOS()
{
BuildAssetBundle(BuildTarget.iOS,false);
}
/// <summary>
/// 建立ab包
/// </summary>
/// <param name="isReBuild">是否清空重新建立</param>
static void BuildAssetBundle(BuildTarget buildTarget, bool isReBuild)
{
string tempAB = "";
string hotUpdateSavePath = "";
if (buildTarget == BuildTarget.Android)
{
tempAB = beginPath "TempAB/Android";
hotUpdateSavePath = beginPath HotDataContext.HotDirector "/Android";//string.Format("{0}/{1}", Application.streamingAssetsPath, HotDataContext.HotDirector);
}
else
{
tempAB = beginPath "TempAB/Ios";
hotUpdateSavePath= beginPath HotDataContext.HotDirector "/Ios";
}
string outputPath = string.Format("{0}/{1}", hotUpdateSavePath, HotDataContext.Assetbundles);
if (Directory.Exists(hotUpdateSavePath))
{
if (isReBuild)
{
Directory.Delete(hotUpdateSavePath, true);
Directory.CreateDirectory(hotUpdateSavePath);
}
}
else
Directory.CreateDirectory(hotUpdateSavePath);
if (Directory.Exists(tempAB))
{
if (isReBuild)
{
Directory.Delete(tempAB, true);
Directory.CreateDirectory(tempAB);
}
}
else
Directory.CreateDirectory(tempAB);
BuildPipeline.BuildAssetBundles(tempAB, BuildAssetBundleOptions.ChunkBasedCompression, buildTarget);//分平台打包,可自动切换平台
if (Directory.Exists(outputPath))
{
DirectoryInfo dirinfo = new DirectoryInfo(outputPath);
FileInfo[] fs = dirinfo.GetFiles("*.*", SearchOption.AllDirectories);
foreach (FileInfo f in fs)
{
string ext_name = Path.GetExtension(f.Name);
if (ext_name == ".meta" || ext_name == ".DS_Store") continue;
File.Delete(f.FullName);
}
}else
Directory.CreateDirectory(outputPath);
//ab目录分类 场景(Scenes)、Resources(Resources)、其他依赖ab(Others)
string abResources = string.Format("{0}/{1}", outputPath, HotDataContext.ResourcesDirector);
string abScenes = string.Format("{0}/{1}", outputPath, HotDataContext.ScenesDirector);
string abOhters= string.Format("{0}/{1}", outputPath, HotDataContext.OhtersDirector);
if (!Directory.Exists(abResources)) Directory.CreateDirectory(abResources);
if (!Directory.Exists(abScenes)) Directory.CreateDirectory(abScenes);
if (!Directory.Exists(abOhters)) Directory.CreateDirectory(abOhters);
string[] files = Directory.GetFiles(tempAB);
int ii = 0;
for (int i=0; i<files.Length; i )
{
string filePath = files[i];
string fileName = Path.GetFileName(filePath);
string exten = Path.GetExtension(fileName);
if (exten == ".manifest"||exten == ".meta") continue;
ii ;
EditorUtility.DisplayProgressBar("重新导入", ii.ToString(), i/ (float)files.Length);
if (fileName.IndexOf(HotDataContext.resourcesAbName) == 0)//Resources里文件
{
File.Copy(filePath, string.Format("{0}/{1}", abResources, fileName));
}
else if (fileName.Contains(HotDataContext.sceneExten))//场景类型
{
File.Copy(filePath, string.Format("{0}/{1}", abScenes, fileName));
}
else if (string.IsNullOrEmpty(exten))
{
//ab依赖描述
File.Copy(filePath, string.Format("{0}/{1}", outputPath, HotDataContext.Assetbundles));
}
else
{
//其他依赖ab包
File.Copy(filePath, string.Format("{0}/{1}", abOhters, fileName));
}
}
EditorUtility.ClearProgressBar();
AssetDatabase.Refresh();
System.Diagnostics.Process.Start(hotUpdateSavePath);
}
#endregion
#region 一键重新建立ab包
[MenuItem("HotTools/一键重新建立AB包(Android)")]
static void OneKeyBuildABAndroid()
{
ClearABNames();
SetAssetBundleName();
BuildAssetBundle(BuildTarget.Android,true);
}
[MenuItem("HotTools/一键重新建立AB包(IOS)")]
static void OneKeyBuildABIOS()
{
ClearABNames();
SetAssetBundleName();
BuildAssetBundle(BuildTarget.iOS,true);
}
#endregion
}
标签: AB
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


网友评论
我要评论