123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.IO;
- using System.Security.Cryptography;
- using System.Text;
- using TModule.Runtime;
- using UnityEditor;
- using UnityEngine;
- using LitJson;
- namespace TModule.Editor
- {
- public class AssetBudleTool : EditorWindow
- {
- private string AssetBudleConfigName= "AssetBundleConfig.asset";
- private string AssetBudleConfigPath;
- private string AssetbudleToolConfigName = "BudleToolConfig.asset";
- private string AssetbudleToolConfigPath;
- private AssetBudleConfig _list;
- private AssetBudleConfig BudleConfig
- {
- get
- {
- _list = _list ?? AssetDatabase.LoadAssetAtPath<AssetBudleConfig>(AssetBudleConfigPath);
- if(_list==null)
- {
- _list = CreateInstance<AssetBudleConfig>();
- AssetDatabase.CreateAsset(_list, AssetBudleConfigPath);
- }
- return _list;
- }
- set => _list = value;
- }
- private AssetBudleToolConfig _toolConfig;
- private AssetBudleToolConfig BudleToolConfig
- {
- get
- {
- _toolConfig = _toolConfig ?? AssetDatabase.LoadAssetAtPath<AssetBudleToolConfig>(AssetbudleToolConfigPath);
- if(_toolConfig==null)
- {
- _toolConfig = CreateInstance<AssetBudleToolConfig>();
- AssetDatabase.CreateAsset(_toolConfig, AssetbudleToolConfigPath);
- }
- return _toolConfig;
- }
- set => _toolConfig = value;
- }
- private static List<VersionDataEntity> versionDatas = new List<VersionDataEntity>();
- private Vector2 _scorllView = Vector2.zero;
- #if UNITY_STANDALONE_WIN
- private BuildTarget _buildTarget = BuildTarget.StandaloneWindows64;
- #elif UNITY_ANDROID
- private BuildTarget _buildTarget = BuildTarget.Android;
- #elif UNITY_IPHON
- private BuildTarget _buildTarget = BuildTarget.iOS;
- #endif
- [MenuItem("TModule/热更/AssetBudleTool")]
- public static void OpenWin()
- {
- AssetBudleTool win = GetWindow<AssetBudleTool>();
- win.maxSize = new Vector2(800, 400);
- win.titleContent.text = "ABTool";
- win.titleContent.image = EditorGUIUtility.IconContent("PrefabModel Icon").image;
- win.Show();
- }
- private void OnEnable()
- {
- var ms = MonoScript.FromScriptableObject(this);
- var path = AssetDatabase.GetAssetPath(ms);
- path = Path.GetDirectoryName(path);
- AssetBudleConfigPath = Path.Combine(path, AssetBudleConfigName);
- AssetbudleToolConfigPath = Path.Combine(path, AssetbudleToolConfigName);
- }
- private void OnGUI()
- {
- using (new EditorGUILayout.HorizontalScope("Box"))
- {
- EditorGUILayout.LabelField("打包平台:", GUILayout.Width(60));
- _buildTarget = (BuildTarget)EditorGUILayout.EnumPopup(_buildTarget);
- EditorGUILayout.LabelField("输出路径:", GUILayout.Width(60));
- BudleToolConfig.m_savePath = EditorGUILayout.TextField(BudleToolConfig.m_savePath);
- if (GUILayout.Button(EditorGUIUtility.IconContent("Project@2x").image, GUILayout.Height(20), GUILayout.Width(40)))
- {
- try
- {
- BudleToolConfig.m_savePath = EditorUtility.OpenFolderPanel("AB包输出路径", "Assets", "Assets");
- }
- catch (Exception e)
- {
- Debug.Log(e.Message);
- }
- }
- }
- float _width = position.width / 6;
- using (new EditorGUILayout.HorizontalScope("Box"))
- {
- EditorGUILayout.LabelField("包名", GUILayout.Width(_width * 4));
- EditorGUILayout.LabelField("文件夹", GUILayout.Width(_width));
- EditorGUILayout.LabelField("操作");
- }
- _scorllView = EditorGUILayout.BeginScrollView(_scorllView);
- for (int i = 0; i < BudleConfig.m_AB.Count; i++)
- {
- using (new EditorGUILayout.HorizontalScope())
- {
- BudleConfig.m_AB[i].m_name = EditorGUILayout.TextField(BudleConfig.m_AB[i].m_name, GUILayout.Width(_width * 4));
- BudleConfig.m_AB[i].m_isFolder = EditorGUILayout.Toggle(BudleConfig.m_AB[i].m_isFolder, GUILayout.Width(_width));
- if (GUILayout.Button(EditorGUIUtility.IconContent("TreeEditor.Trash").image, GUILayout.Height(20)))
- {
- BudleConfig.m_AB.Remove(BudleConfig.m_AB[i]);
- }
- }
- }
- if (GUILayout.Button(EditorGUIUtility.IconContent("CreateAddNew@2x").image, GUILayout.Height(30), GUILayout.Width(30)))
- {
- BudleConfig.m_AB.Add(new AssetBundleEntity());
- }
- EditorGUILayout.EndScrollView();
- if (GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition))
- {
- if (Event.current.type == EventType.DragUpdated)
- DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
- else if (Event.current.type == EventType.DragExited)
- {
- if (DragAndDrop.paths != null && DragAndDrop.paths.Length > 0)
- {
- for (int i = 0; i < DragAndDrop.paths.Length; i++)
- {
- if (BudleConfig.m_AB.Find(p => p.m_name == DragAndDrop.paths[i]) == null)
- BudleConfig.m_AB.Add(new AssetBundleEntity()
- { m_name = DragAndDrop.paths[i] });
- }
- }
- }
- }
- using (new EditorGUILayout.HorizontalScope())
- {
- EditorGUILayout.LabelField("将打包资源拷贝到StreamingAssets文件夹", GUILayout.Width(230));
- BudleToolConfig.m_copyToStreamingAssets = EditorGUILayout.Toggle(BudleToolConfig.m_copyToStreamingAssets);
- }
- if (GUILayout.Button("构建AssetBundle"))
- {
- OnAssetBundleCallBack();
- }
- }
- /// <summary>
- /// 打包回调
- /// </summary>
- private void OnAssetBundleCallBack()
- {
- string tartgetPath = BudleToolConfig.m_savePath + "/" + _buildTarget.ToString();
- if (!Directory.Exists(tartgetPath))
- Directory.CreateDirectory(tartgetPath);
- SetABName();
- BuildPipeline.BuildAssetBundles(tartgetPath, BuildAssetBundleOptions.None, _buildTarget);
- if (BudleToolConfig.m_copyToStreamingAssets)
- CopyToStreamingAssets();
- OnCreateVersionText();
- AssetDatabase.Refresh();
- }
- private void SetABName()
- {
- for (int i = 0; i < BudleConfig.m_AB.Count; i++)
- {
- AssetBundleEntity assetBudle = BudleConfig.m_AB[i];
- if (assetBudle.m_isFolder)
- {
- string[] floderArr = new string[] {GetAbsolutePath(assetBudle.m_name) };
- SaveFolderSettings(floderArr);
- }
- else
- {
- SaveFileSettings(Application.dataPath + "/" + assetBudle.m_name);
- }
- }
- }
- private void SaveFolderSettings(string[] folderArr)
- {
- foreach (string floderPath in folderArr)
- {
- string[] arrFile = Directory.GetFiles(floderPath);
- foreach (string filePah in arrFile)
- {
- SaveFileSettings(filePah);
- }
- string[] arrFolder = Directory.GetDirectories(floderPath);
- SaveFolderSettings(arrFolder);
- }
- }
- private void SaveFileSettings(string filePath)
- {
- FileInfo file = new FileInfo(filePath);
- if (!file.Extension.Equals(".meta", StringComparison.CurrentCultureIgnoreCase))
- {
- int index = filePath.IndexOf("Assets/", StringComparison.CurrentCultureIgnoreCase);
- string newPath = filePath.Substring(index);
- string fileName = newPath.Substring(newPath.IndexOf("Assets/")).Replace(file.Extension, "");
- string variant = file.Extension.Equals(".unity", StringComparison.CurrentCultureIgnoreCase) ? "unity3d" : "assetbundle";
- AssetImporter importer = AssetImporter.GetAtPath(newPath);
- importer.SetAssetBundleNameAndVariant(fileName, variant);
- importer.SaveAndReimport();
- }
- }
- private void CopyToStreamingAssets()
- {
- string toPath = Application.streamingAssetsPath;
- string tartgetPath = BudleToolConfig.m_savePath + "/" + _buildTarget.ToString();
- CopyDirectory(tartgetPath, toPath,true);
- AssetDatabase.Refresh();
- }
- /// <summary>
- /// 创建版本文件
- /// </summary>
- private void OnCreateVersionText()
- {
- string strVersionJsonPath = $"{BudleToolConfig.m_savePath}/{_buildTarget.ToString()}/VersionFile.json";
- versionDatas.Clear();
- if (File.Exists(strVersionJsonPath))
- File.Delete(strVersionJsonPath);
- StringBuilder sbContent = new StringBuilder();
- DirectoryInfo directory = new DirectoryInfo(BudleToolConfig.m_savePath);
- FileInfo[] arrfiles = directory.GetFiles("*", SearchOption.AllDirectories);
- for (int i = 0; i < arrfiles.Length; i++)
- {
- FileInfo file = arrfiles[i];
- string fullName = file.FullName;
- string md5 = GetFileMD5(fullName);
- if (md5 == null) continue;
- string subPath = $"{BudleToolConfig.m_savePath}/{_buildTarget.ToString()}";
- versionDatas.Add(new VersionDataEntity()
- {
- m_fullName = fullName.Substring(fullName.IndexOf(subPath) + subPath.Length + 2),
- m_md5 = md5,
- m_size = Mathf.Ceil(file.Length / 1024.0f)
- });
- }
- WriteJsonData(versionDatas, strVersionJsonPath);
- }
- private void OnDisable()
- {
- EditorUtility.SetDirty(_list);
- EditorUtility.SetDirty(BudleToolConfig);
- AssetDatabase.SaveAssets();
- }
- public string GetAbsolutePath(string path)
- {
- string _path = Application.dataPath.Remove(Application.dataPath.LastIndexOf('/') + 1);
- return _path + path;
- }
- /// <summary>
- /// 拷贝文件夹
- /// </summary>
- /// <param name="sourceDirName"></param>
- /// <param name="destDirName"></param>
- /// <param name="isOverlay">是否覆盖已有同名文件</param>
- public void CopyDirectory(string sourceDirName, string destDirName, bool isOverlay = false)
- {
- try
- {
- if (!Directory.Exists(destDirName))
- {
- Directory.CreateDirectory(destDirName);
- File.SetAttributes(destDirName, File.GetAttributes(sourceDirName));
- }
- if (destDirName[destDirName.Length - 1] != Path.DirectorySeparatorChar)
- destDirName = destDirName + Path.DirectorySeparatorChar;
- string[] files = Directory.GetFiles(sourceDirName);
- foreach (string file in files)
- {
- if (File.Exists(destDirName + Path.GetFileName(file)) && !isOverlay)
- continue;
- FileInfo fileInfo = new FileInfo(file);
- if (fileInfo.Extension.Equals(".meta", StringComparison.CurrentCultureIgnoreCase))
- continue;
- File.Copy(file, destDirName + Path.GetFileName(file), true);
- File.SetAttributes(destDirName + Path.GetFileName(file), FileAttributes.Normal);
- }
- string[] dirs = Directory.GetDirectories(sourceDirName);
- foreach (string dir in dirs)
- {
- CopyDirectory(dir, destDirName + Path.GetFileName(dir), isOverlay);
- }
- }
- catch (Exception ex)
- {
- throw ex;
- }
- }
- /// <summary>
- /// 写入数据
- /// </summary>
- /// <param name="data">数据</param>
- /// <param name="path">文件完整路径</param>
- public static void WriteJsonData(object data, string path)
- {
- string json = JsonMapper.ToJson(data);
- using (StreamWriter sw = new StreamWriter(path))
- {
- //保存数据
- sw.WriteLine(json);
- //关闭文档
- sw.Close();
- sw.Dispose();
- }
- }
- /// <summary>
- /// 获取文件MD5
- /// </summary>
- /// <param name="filePath"></param>
- /// <returns></returns>
- public static string GetFileMD5(string filePath)
- {
- if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
- return null;
- try
- {
- FileStream file = new FileStream(filePath, FileMode.Open);
- MD5 mD5 = new MD5CryptoServiceProvider();
- byte[] byteResult = mD5.ComputeHash(file);
- string strResult = BitConverter.ToString(byteResult);
- strResult = strResult.Replace("-", "");
- return strResult;
- }
- catch
- {
- return null;
- }
- }
- }
- }
|