PackageService.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using UnityEditor;
  6. using UnityEngine;
  7. #pragma warning disable
  8. public static class PackageService
  9. {
  10. #region 4.0旧版本打包
  11. static BuildAssetBundleOptions relyBuildOption = BuildAssetBundleOptions.AppendHashToAssetBundleName; //每次二进制一致 //依赖包打包设置
  12. // | BuildAssetBundleOptions.ForceRebuildAssetBundle;
  13. // | BuildAssetBundleOptions.CollectDependencies; //收集依赖
  14. // | BuildAssetBundleOptions.CompleteAssets; //完整资源
  15. // | BuildAssetBundleOptions.ChunkBasedCompression; //块压缩
  16. static BuildAssetBundleOptions bundleBuildOption = BuildAssetBundleOptions.DeterministicAssetBundle //每次二进制一致 //Bundle打包设置
  17. | BuildAssetBundleOptions.CollectDependencies //收集依赖
  18. | BuildAssetBundleOptions.CompleteAssets; //完整资源
  19. //| BuildAssetBundleOptions.ChunkBasedCompression; //块压缩
  20. public static BuildTarget GetTargetPlatform
  21. {
  22. get
  23. {
  24. BuildTarget target = BuildTarget.StandaloneWindows;
  25. #if UNITY_ANDROID //安卓
  26. target = BuildTarget.Android;
  27. #elif UNITY_IOS //iPhone
  28. target = BuildTarget.iOS;
  29. #elif UNITY_WEBGL //WebGL
  30. target = BuildTarget.WebGL;
  31. #endif
  32. return target;
  33. }
  34. }
  35. public static IEnumerator Package(List<EditPackageConfig> relyPackages, List<EditPackageConfig> bundles, PackageCallBack callBack)
  36. {
  37. BuildPipeline.PushAssetDependencies();
  38. float sumCount = relyPackages.Count + bundles.Count;
  39. float currentCount = 0;
  40. callBack(0, "删除旧资源");
  41. yield return 0;
  42. //删除streaming下所有旧资源
  43. if (Directory.Exists(Application.dataPath + "/StreamingAssets"))
  44. {
  45. FileTool.DeleteDirectory(Application.dataPath + "/StreamingAssets");
  46. }
  47. callBack(0, "开始打包");
  48. yield return 0;
  49. //先打依赖包
  50. for (int i = 0; i < relyPackages.Count; i++)
  51. {
  52. PackageRelyPackage(relyPackages[i]);
  53. currentCount++;
  54. callBack(currentCount / sumCount, "打包依赖包 第" + i + "个 共" + relyPackages.Count + "个");
  55. yield return 0;
  56. }
  57. //再打普通包
  58. for (int i = 0; i < bundles.Count; i++)
  59. {
  60. PackageBundle(bundles[i]);
  61. currentCount++;
  62. callBack(currentCount / sumCount, "打包普通包 第" + i + "个 共" + bundles.Count + "个");
  63. yield return 0;
  64. }
  65. BuildPipeline.PopAssetDependencies();
  66. AssetDatabase.Refresh();
  67. }
  68. public static void Package(List<EditPackageConfig> relyPackages, List<EditPackageConfig> bundles)
  69. {
  70. BuildPipeline.PushAssetDependencies();
  71. //删除streaming下所有旧资源
  72. if (Directory.Exists(Application.dataPath + "/StreamingAssets"))
  73. {
  74. FileTool.SafeDeleteDirectory(Application.dataPath + "/StreamingAssets");
  75. }
  76. //先打依赖包
  77. for (int i = 0; i < relyPackages.Count; i++)
  78. {
  79. PackageRelyPackage(relyPackages[i]);
  80. }
  81. //再打普通包
  82. for (int i = 0; i < bundles.Count; i++)
  83. {
  84. PackageBundle(bundles[i]);
  85. }
  86. BuildPipeline.PopAssetDependencies();
  87. AssetDatabase.Refresh();
  88. }
  89. static void PackageRelyPackage(EditPackageConfig package)
  90. {
  91. //BuildPipeline.PushAssetDependencies();
  92. if (package.objects.Count == 0)
  93. {
  94. Debug.LogError(package.name + " 没有资源!");
  95. }
  96. UnityEngine.Object[] res = new UnityEngine.Object[package.objects.Count];
  97. for (int i = 0; i < package.objects.Count; i++)
  98. {
  99. res[i] = package.objects[i].obj;
  100. }
  101. string path = GetExportPath(package.path, package.name);
  102. FileTool.CreatFilePath(path);
  103. if (package.isCollectDependencies)
  104. {
  105. BuildPipeline.BuildAssetBundle(null, res, path, relyBuildOption, GetTargetPlatform);
  106. }
  107. else
  108. {
  109. BuildAssetBundleOptions bbo = BuildAssetBundleOptions.DeterministicAssetBundle;
  110. BuildPipeline.BuildAssetBundle(null, res, path, bbo, GetTargetPlatform);
  111. }
  112. }
  113. public static void PackageBundle(EditPackageConfig package)
  114. {
  115. //导入资源包
  116. BuildPipeline.PushAssetDependencies();
  117. //打包
  118. UnityEngine.Object[] res = new UnityEngine.Object[package.objects.Count];
  119. for (int i = 0; i < package.objects.Count; i++)
  120. {
  121. res[i] = package.objects[i].obj;
  122. }
  123. string path = GetExportPath(package.path, package.name);
  124. FileTool.CreatFilePath(path);
  125. BuildPipeline.BuildAssetBundle(package.mainObject.obj, res, path, bundleBuildOption, GetTargetPlatform);
  126. BuildPipeline.PopAssetDependencies();
  127. }
  128. static string GetExportPath(string path, string name)
  129. {
  130. return Application.dataPath + "/StreamingAssets/" + BundleConfigEditorWindow.GetRelativePath(FileTool.RemoveExpandName(path)).ToLower();
  131. }
  132. static void CopyFile(string fileName)
  133. {
  134. string filePath = PathTool.GetAbsolutePath(ResLoadLocation.Resource, fileName + "." + ConfigManager.c_expandName);
  135. string exportPath = PathTool.GetAbsolutePath(ResLoadLocation.Streaming, fileName + "." + ConfigManager.c_expandName);
  136. if (File.Exists(filePath))
  137. {
  138. Debug.Log("导出 " + exportPath);
  139. File.Copy(filePath, exportPath, true);
  140. }
  141. else
  142. {
  143. Debug.Log(filePath + " 不存在");
  144. }
  145. }
  146. public delegate void PackageCallBack(float progress, string content);
  147. #endregion
  148. #region 5.0新版本打包
  149. public const string c_StreamingAssetsPath = "/StreamingAssets/";
  150. public const string c_ResourceParentPath = "/Resources/";
  151. public const string c_AssetsParentPath = "Assets/";
  152. public static void Package_5_0(bool deleteManifestFile)
  153. {
  154. string streamingPath = Application.dataPath + c_StreamingAssetsPath;
  155. //删除streaming下所有旧资源
  156. if (Directory.Exists(streamingPath))
  157. {
  158. FileTool.DeleteDirectory(streamingPath);
  159. }
  160. else
  161. {
  162. FileTool.CreatPath(streamingPath);
  163. }
  164. Debug.Log("GetTargetPlatform " + PackageService.GetTargetPlatform);
  165. BuildPipeline.BuildAssetBundles(streamingPath, BuildAssetBundleOptions.None, PackageService.GetTargetPlatform);
  166. //删除冗余的清单文件
  167. if (deleteManifestFile)
  168. {
  169. DeleteManifestFile(streamingPath);
  170. }
  171. AssetDatabase.Refresh();
  172. }
  173. /// <summary>
  174. /// 清除所有AssetsBundle设置
  175. /// </summary>
  176. public static void ClearAssetBundlesName()
  177. {
  178. string[] oldAssetBundleNames = AssetDatabase.GetAllAssetBundleNames();
  179. int count = oldAssetBundleNames.Length;
  180. for (int j = 0; j < oldAssetBundleNames.Length; j++)
  181. {
  182. AssetDatabase.RemoveAssetBundleName(oldAssetBundleNames[j], true);
  183. EditorUtility.DisplayProgressBar("清除Bundle名字", "进度", j / count);
  184. }
  185. EditorUtility.ClearProgressBar();
  186. }
  187. //构造相对路径使用
  188. static int direIndex = 0;
  189. static int assetsIndex = 0;
  190. static string resourcePath;
  191. static Dictionary<string, string> nameDict = new Dictionary<string, string>();
  192. static Dictionary<string, bool> pathDict = new Dictionary<string, bool>();
  193. public static void SetAssetBundlesName()
  194. {
  195. //nameDict.Clear();
  196. pathDict.Clear();
  197. int length = AssetDatabase.GetAllAssetBundleNames().Length;
  198. Debug.Log("生成前 bundle数目 " + length);
  199. //构造相对路径使用
  200. resourcePath = Application.dataPath + c_ResourceParentPath;
  201. direIndex = resourcePath.LastIndexOf(c_ResourceParentPath);
  202. direIndex += c_ResourceParentPath.Length;
  203. assetsIndex = resourcePath.LastIndexOf(c_AssetsParentPath);
  204. RecursionDirectory(Application.dataPath + "/Resources/");
  205. length = AssetDatabase.GetAllAssetBundleNames().Length;
  206. Debug.Log("生成后 bundle数目 " + length);
  207. //string[] allFilePath= HDJ.Framework.Utils.PathUtils.GetDirectoryFilePath("Assets/Resources/");
  208. //foreach (var path in allFilePath)
  209. //{
  210. // if (path.EndsWith(".meta") || path.EndsWith(".exe"))
  211. // continue;
  212. // else
  213. // {
  214. // string relativePath = FileTool.RemoveExpandName(f.Substring(direIndex));
  215. // string assetsPath = f.Substring(assetsIndex);
  216. // Object obj = Resources.Load(relativePath);
  217. // if (obj == null)
  218. // {
  219. // Debug.LogError("Resources obj is null ->" + relativePath);
  220. // }
  221. // SetAssetBundle(obj, assetsPath);
  222. // }
  223. //}
  224. }
  225. //递归所有目录
  226. static void RecursionDirectory(string path)
  227. {
  228. if (!File.Exists(path))
  229. {
  230. FileTool.CreatPath(path);
  231. }
  232. string[] dires = Directory.GetDirectories(path);
  233. for (int i = 0; i < dires.Length; i++)
  234. {
  235. RecursionDirectory(dires[i]);
  236. }
  237. string[] files = Directory.GetFiles(path);
  238. for (int i = 0; i < files.Length; i++)
  239. {
  240. string f = files[i];
  241. if (f.EndsWith(".meta")|| f.EndsWith(".exe"))
  242. continue;
  243. else
  244. {
  245. string relativePath = FileTool.RemoveExpandName(f.Substring(direIndex));
  246. string assetsPath = f.Substring(assetsIndex);
  247. UnityEngine.Object obj = Resources.Load(relativePath);
  248. if (obj == null)
  249. {
  250. Debug.LogError("Resources obj is null ->" + relativePath);
  251. }
  252. SetAssetBundle(obj, assetsPath);
  253. }
  254. }
  255. }
  256. /// <summary>
  257. /// 获取所有相关资源
  258. /// </summary>
  259. /// <param name="go">目标对象</param>
  260. /// <returns>所有相关资源</returns>
  261. static UnityEngine.Object[] GetCorrelationResource(UnityEngine.Object go)
  262. {
  263. UnityEngine.Object[] roots = new UnityEngine.Object[] { go };
  264. return EditorUtility.CollectDependencies(roots);
  265. }
  266. static void SetAssetBundle(UnityEngine.Object obj,string path)
  267. {
  268. //寻找资源的依赖,将其设为ABN
  269. AssetImporter assetImporter = AssetImporter.GetAtPath(path);
  270. UnityEngine.Object[] objs = GetCorrelationResource(obj);
  271. for (int i = 0; i < objs.Length; i++)
  272. {
  273. if(!ComponentFilter(objs[i]))
  274. {
  275. string tmp = AssetDatabase.GetAssetPath(objs[i]);
  276. SetAssetsBundleName(tmp);
  277. }
  278. }
  279. //将资源设为ABN
  280. SetAssetsBundleName(path);
  281. }
  282. static void SetAssetsBundleName(string path)
  283. {
  284. if(pathDict.ContainsKey(path))
  285. {
  286. return;
  287. }
  288. else
  289. {
  290. pathDict.Add(path,true);
  291. }
  292. //if(path.Contains(" "))
  293. //{
  294. // Debug.LogError("SetAssetsBundleName 文件或路径有空格!->" + path + "<-");
  295. // return;
  296. //}
  297. //Resources下的资源单独打包
  298. //Res下的资源以文件夹为单位打包
  299. //移除文件夹中的下划线
  300. //移除空格
  301. string name = FileTool.RemoveExpandName(path).ToLower().Replace("/_","/").Replace("assets/", "").Replace(" ", "");
  302. if (name.Contains("resources/"))
  303. {
  304. name = name.Replace("resources/", "");
  305. }
  306. else
  307. {
  308. name = FileTool.GetUpperPath(name);
  309. name = "rely/" + name.Replace("/", "_");
  310. }
  311. string fileName = FileTool.GetFileNameBySring(name);
  312. string upperPath = FileTool.GetUpperPath(name);
  313. ////重复判断
  314. //if (nameDict.ContainsKey(fileName))
  315. //{
  316. // if(upperPath != nameDict[fileName])
  317. // {
  318. // Debug.LogError("文件名重复! ->" + name + "<- A:" + upperPath + " b:" + nameDict[fileName]);
  319. // }
  320. //}
  321. //else
  322. //{
  323. // nameDict.Add(fileName, upperPath);
  324. //}
  325. AssetImporter assetImporter = AssetImporter.GetAtPath(path);
  326. if (assetImporter != null)
  327. {
  328. assetImporter.assetBundleName = name;
  329. }
  330. else
  331. {
  332. Debug.LogError("SetAssetsInfo relyPackages error :->" + path);
  333. }
  334. }
  335. static bool ComponentFilter(UnityEngine.Object comp)
  336. {
  337. //过滤掉unity自带对象
  338. string path = AssetDatabase.GetAssetPath(comp);
  339. if (path.IndexOf("Assets") != 0)
  340. {
  341. return true;
  342. }
  343. ////过滤掉所有shander
  344. //if (comp as Shader != null)
  345. //{
  346. // if (!shaderFilter.ContainsKey(comp.ToString()))
  347. // {
  348. // shaderFilter.Add(comp.ToString(), (Shader)comp);
  349. // Debug.LogWarning("包含 Shader! :" + comp.ToString());
  350. // }
  351. // return true;
  352. //}
  353. if (comp is MonoScript)
  354. {
  355. return true;
  356. }
  357. return false;
  358. }
  359. /// <summary>
  360. /// 删除打包后冗余的Manifest文件
  361. /// </summary>
  362. /// <param name="path"></param>
  363. public static void DeleteManifestFile(string path)
  364. {
  365. string[] dires = Directory.GetDirectories(path);
  366. for (int i = 0; i < dires.Length; i++)
  367. {
  368. DeleteManifestFile(dires[i]);
  369. }
  370. string[] files = Directory.GetFiles(path);
  371. for (int i = 0; i < files.Length; i++)
  372. {
  373. if (files[i].EndsWith(".manifest")
  374. || files[i].EndsWith(".meta"))
  375. {
  376. File.Delete(files[i]);
  377. }
  378. }
  379. }
  380. #endregion
  381. ///// <summary>
  382. ///// 设置Resources目录下所有资源的BundleName
  383. ///// </summary>
  384. ///// <param name="path"></param>
  385. ///// <param name="endsWith"></param>
  386. //public static void SetAllResourceBundleName(string path, string[] endsWith)
  387. //{
  388. // string[] pathArr = HDJ.Framework.Utils.PathUtils.GetDirectoryFilePath(path, endsWith);
  389. // for (int i = 0; i < pathArr.Length; i++)
  390. // {
  391. // string filePath = pathArr[i];
  392. // if (filePath.EndsWith(".meta"))
  393. // continue;
  394. // string s = Path.GetFileNameWithoutExtension(filePath);
  395. // //if (s == AssetsPathController.PathFileName)
  396. // // continue;
  397. // SetBundleName(filePath);
  398. // }
  399. // Debug.Log("bundleName数目:" + bundleNameDics.Count);
  400. // int index = 0;
  401. // int count = bundleNameDics.Count;
  402. // foreach (var item in bundleNameDics)
  403. // {
  404. // index++;
  405. // item.Key.assetBundleName = item.Value;
  406. // EditorUtility.DisplayProgressBar("设置Bundle名字", "进度", index / count);
  407. // }
  408. // bundleNameDics.Clear();
  409. // EditorUtility.ClearProgressBar();
  410. // Debug.Log("生成后 bundle数目 " + AssetDatabase.GetAllAssetBundleNames().Length);
  411. // //foreach (var item in assetTypeDic)
  412. // //{
  413. // // Debug.Log("assetType:" + item.Key.FullName + " : " + item.Value);
  414. // //}
  415. //}
  416. //private const string ResPathDirName = "Assets/Resources/";
  417. //private static Dictionary<AssetImporter, string> bundleNameDics = new Dictionary<AssetImporter, string>();
  418. //public const string EndsWith_assetbundle = ".assetbundle";
  419. ////private static Dictionary<Type, string> assetTypeDic = new Dictionary<Type, string>();
  420. //private static void SetBundleName(string filePath)
  421. //{
  422. // AssetImporter assetImporter = AssetImporter.GetAtPath(filePath);
  423. // if (assetImporter)
  424. // {
  425. // if (assetImporter.GetType() == typeof(MonoImporter))
  426. // return;
  427. // if (bundleNameDics.ContainsKey(assetImporter))
  428. // return;
  429. // string bundleName = null;
  430. // //Resources 文件夹下面资源的命名方式
  431. // if (filePath.Contains(ResPathDirName))
  432. // {
  433. // bundleName = HDJ.Framework.Utils.PathUtils.CutPath(filePath, "Resources");
  434. // bundleName = bundleName.Replace(Path.GetExtension(bundleName), EndsWith_assetbundle);
  435. // // assetImporter.assetBundleName = bundleName;
  436. // }
  437. // else
  438. // {
  439. // string name = FileTool.RemoveExpandName(filePath).ToLower().Replace("/_", "/").Replace("assets/", "").Replace(" ", "");
  440. // name = FileTool.GetUpperPath(name);
  441. // name = "rely/" + name.Replace("/", "_");
  442. // //string dir = Path.GetDirectoryName(filePath);
  443. // //dir = dir.Replace("\\", "/");
  444. // //bundleName = dir + "/" + dir.Replace("/", "_") + EndsWith_assetbundle;
  445. // bundleName = name;
  446. // }
  447. // bundleNameDics.Add(assetImporter, bundleName);
  448. // //if (!assetTypeDic.ContainsKey(assetImporter.GetType()))
  449. // //{
  450. // // assetTypeDic.Add(assetImporter.GetType(), filePath);
  451. // //}
  452. // if (assetImporter.GetType() == typeof(AudioImporter))
  453. // return;
  454. // if (assetImporter.GetType() == typeof(TextureImporter))
  455. // return;
  456. // if (assetImporter.GetType() == typeof(ShaderImporter))
  457. // return;
  458. // Type assetType = AssetDatabase.GetMainAssetTypeAtPath(filePath);
  459. // if (assetType == typeof(TextAsset))
  460. // return;
  461. // if (assetType == typeof(AnimationClip))
  462. // return;
  463. // string[] deps = AssetDatabase.GetDependencies(filePath);
  464. // foreach (var tempPath in deps)
  465. // {
  466. // if (tempPath.Contains(ResPathDirName))
  467. // {
  468. // continue;
  469. // }
  470. // SetBundleName(tempPath);
  471. // }
  472. // }
  473. //}
  474. }