CmdExportAssets.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. using XGame.Editor.Build.AssetBundles;
  4. using XGame.Framework.Json;
  5. using XFADefine = XGame.Framework.Asset.Define;
  6. namespace XGame.Editor.Build
  7. {
  8. public struct AbEncryptInfo
  9. {
  10. public long bundleId;
  11. public string originBundleName;
  12. public uint offset;
  13. }
  14. [BuildCommand((uint)BuildCommandPriority.ExportAssets)]
  15. class CmdExportAssets : BaseBuildCommand, ICommandExecuter
  16. {
  17. #region copy assets
  18. /// <summary>
  19. /// 异或加密使用的key值:1023
  20. /// </summary>
  21. const int encryptKey = 0x03FF;
  22. Dictionary<string, AbEncryptInfo> CollectAbEncryptInfos()
  23. {
  24. var abEncryptInfos = new Dictionary<string, AbEncryptInfo>();
  25. var abmanifest = AssetBundleBackupManifest.Load();
  26. if (abmanifest != null)
  27. {
  28. //manifest包的加密信息
  29. var encrypt = new AbEncryptInfo()
  30. {
  31. bundleId = long.Parse(XFADefine.MANIFEST_BUNDLE_NAME),
  32. originBundleName = XFADefine.MANIFEST_BUNDLE_NAME,
  33. offset = XFADefine.MANIFEST_BUNDLE_OFFSET
  34. };
  35. abEncryptInfos.Add(XFADefine.MANIFEST_BUNDLE_NAME, encrypt);
  36. var abInfos = abmanifest.bundleInfos;
  37. foreach (var abInfo in abInfos)
  38. {
  39. encrypt = new AbEncryptInfo()
  40. {
  41. bundleId = abInfo.bundleId,
  42. originBundleName = abInfo.nameOrGuid,
  43. offset = abInfo.offset
  44. };
  45. abEncryptInfos.Add(encrypt.bundleId.ToString(), encrypt);
  46. }
  47. }
  48. return abEncryptInfos;
  49. }
  50. private Dictionary<string, string> CollectBundleCrc()
  51. {
  52. var bundleCrcMap = new Dictionary<string, string>();
  53. var manifestPath = Asset.PathDefine.AssetBundleOutputPath + "/BundleCrcInfoManifest.manifest";
  54. if (System.IO.File.Exists(manifestPath))
  55. {
  56. var text = System.IO.File.ReadAllText(manifestPath);
  57. var manifest = XJson.ToObject<BundleCrcInfoManifest>(text);
  58. if (manifest.bundleInfos != null)
  59. {
  60. foreach (var info in manifest.bundleInfos)
  61. {
  62. bundleCrcMap.Add(info.bundleName, info.bundleCRC);
  63. }
  64. }
  65. }
  66. return bundleCrcMap;
  67. }
  68. byte[] ReadAllBytes(string assetPath, Dictionary<string, AbEncryptInfo> abEncryptInfos)
  69. {
  70. byte[] bytes = System.IO.File.ReadAllBytes(assetPath);
  71. if (assetPath.Contains(Asset.PathDefine.AssetBundleOutputPath))
  72. {
  73. var fileName = System.IO.Path.GetFileNameWithoutExtension(assetPath);
  74. if (!abEncryptInfos.TryGetValue(fileName, out var encryptInfo))
  75. return bytes;
  76. if (encryptInfo.offset <= 0) return bytes;
  77. var encryptData = System.Text.Encoding.UTF8.GetBytes(encryptInfo.originBundleName);
  78. for (var i = 0; i < encryptData.Length; i++) // 依次对字符串中各字符进行操作
  79. {
  80. var current = encryptData[i];
  81. encryptData[i] = (byte)(current ^ encryptKey); // 将密钥与字符异或
  82. }
  83. //var fileData = System.IO.File.ReadAllBytes(assetPath);
  84. var length = bytes.Length + encryptInfo.offset;
  85. var buffer = new byte[length];
  86. System.Array.Copy(encryptData, 0, buffer, 0, encryptInfo.offset);
  87. System.Array.Copy(bytes, 0, buffer, encryptInfo.offset, bytes.Length);
  88. return buffer;
  89. }
  90. return bytes;
  91. }
  92. void WriteAllBytes(string path, byte[] bytes)
  93. {
  94. var destDir = Asset.FileUtil.GetDirectoryName(path, true);
  95. if (!System.IO.Directory.Exists(destDir))
  96. System.IO.Directory.CreateDirectory(destDir);
  97. System.IO.File.WriteAllBytes(path, bytes);
  98. }
  99. void CopyAssets(string streamingAssetsPath, Dictionary<string, string> assetMap, Dictionary<string, AbEncryptInfo> abEncryptInfos)
  100. {
  101. foreach (var item in assetMap)
  102. {
  103. string assetPath = item.Key;
  104. if (!System.IO.File.Exists(assetPath))
  105. {
  106. BuildLog.Error($"Asset can not found:{assetPath}");
  107. return;
  108. }
  109. byte[] bytes = ReadAllBytes(assetPath, abEncryptInfos);
  110. string toPath = System.IO.Path.Combine(streamingAssetsPath, item.Value);
  111. WriteAllBytes(toPath, bytes);
  112. }
  113. }
  114. #endregion
  115. //#region split assets
  116. //void CollectionExpansionAssetInfos(ProductAssetsContext assetsContext, Dictionary<string, string> assetMap, out Dictionary<string, EditorAssetInfo> assetInfos, out CustomPackageInfo[] customPackageInfos)
  117. //{
  118. // assetInfos = new Dictionary<string, EditorAssetInfo>(assetMap.Count);
  119. // foreach (var item in assetMap)
  120. // {
  121. // EditorAssetInfo assetInfo = new EditorAssetInfo();
  122. // assetInfo.packageId = ManifestUtilities.MainAssetId;
  123. // assetInfo.path = item.Value;
  124. // assetInfos.Add(item.Key, assetInfo);
  125. // }
  126. // if (Context.config.ignoreSplitAssets)
  127. // {
  128. // customPackageInfos = null;
  129. // return;
  130. // }
  131. // CustomPackageControl customPackageControl = new CustomPackageControl(assetsContext);
  132. // customPackageControl.CollectPackages();
  133. // customPackageInfos = customPackageControl.GeneratePackages();
  134. // Dictionary<string, string> assetPkgMap = new Dictionary<string, string>();
  135. // if (null != customPackageInfos && customPackageInfos.Length > 0)
  136. // {
  137. // foreach (var pkgInfo in customPackageInfos)
  138. // {
  139. // var errors = customPackageControl.GetPackageErrors(pkgInfo.uid);
  140. // if (null != errors && errors.Length > 0)
  141. // {
  142. // foreach (var error in errors)
  143. // {
  144. // BuildLog.Warn("[GenExpancePackageManifest] discover error asset! uid: {0}, id: {1}, error code:{2}, is ext asset: {3} addressable: {4}\nerror asset path:{5}\nsource:{6}"
  145. // , pkgInfo.uid, pkgInfo.packageID, error.code, error.asset.isExtAsset, error.asset.addressable, error.asset.assetPath, error.asset.source);
  146. // }
  147. // }
  148. // foreach (var path in pkgInfo.assetPaths)
  149. // {
  150. // assetPkgMap.Add(path, pkgInfo.packageID);
  151. // }
  152. // }
  153. // }
  154. // foreach (var item in assetPkgMap)
  155. // {
  156. // if (!assetInfos.TryGetValue(item.Key, out var assetInfo))
  157. // {
  158. // BuildLog.Warn($"Expansion path not found in assets: {item.Key}");
  159. // continue;
  160. // }
  161. // assetInfo.packageId = item.Value;
  162. // }
  163. //}
  164. //void SplitAssets(string outputDir, string streamingAssetsPath, Dictionary<string, EditorAssetInfo> assetInfos)
  165. //{
  166. // foreach (var assetInfo in assetInfos.Values)
  167. // {
  168. // bool isMainAsset = assetInfo.packageId == ManifestUtilities.MainAssetId || string.IsNullOrEmpty(assetInfo.packageId);
  169. // string toPath = GetOutputPath(outputDir, assetInfo.path, isMainAsset, assetInfo.packageId);
  170. // var destDir = KAFileUtil.GetDirectoryName(toPath, true);
  171. // if (!System.IO.Directory.Exists(destDir)) System.IO.Directory.CreateDirectory(destDir);
  172. // string fromPath = System.IO.Path.Combine(streamingAssetsPath, assetInfo.path);
  173. // if (isMainAsset)
  174. // System.IO.File.Copy(fromPath, toPath);
  175. // else
  176. // System.IO.File.Move(fromPath, toPath);
  177. // }
  178. //}
  179. //#endregion
  180. //#region generate runtime-configs
  181. //ExpansionPackageManifest GenerateUniquePackageManifest(string outputDir, string streamingAssetsPath, CustomPackageInfo[] customPackageInfos, ref Dictionary<string, EditorAssetInfo> assetInfos)
  182. //{
  183. // if (null == customPackageInfos || customPackageInfos.Length <= 0) return null;
  184. // List<ExpansionPackageInfo> infos = new List<ExpansionPackageInfo>();
  185. // foreach (var item in customPackageInfos)
  186. // {
  187. // if (item.isShared) continue;
  188. // if ((null == item.assetPaths || item.assetPaths.Length <= 0) && (null == item.dependencies || item.dependencies.Length <= 0)) continue;
  189. // var info = new ExpansionPackageInfo()
  190. // {
  191. // downloadMode = item.downloadMode,
  192. // id = item.packageID,
  193. // priority = item.priority,
  194. // name = item.packageName,
  195. // updateMode = item.updateMode,
  196. // };
  197. // info.dependencies = new string[item.dependencies.Length];
  198. // item.dependencies.CopyTo(info.dependencies, 0);
  199. // infos.Add(info);
  200. // }
  201. // ExpansionPackageManifest manifest = new ExpansionPackageManifest();
  202. // manifest.packageInfos = infos.ToArray();
  203. // string outputPath = System.IO.Path.Combine(outputDir, "packages", "main", "assets");
  204. // ManifestUtilities.SaveUniquePackageManifest(outputPath, manifest);
  205. // string fromPath = System.IO.Path.Combine(outputPath, ManifestUtilities.AssetManifestRelativePath, "UniquePackages.manifest");
  206. // string toDir = System.IO.Path.Combine(streamingAssetsPath, ManifestUtilities.AssetManifestRelativePath);
  207. // if (!System.IO.Directory.Exists(toDir)) System.IO.Directory.CreateDirectory(toDir);
  208. // string toPath = System.IO.Path.Combine(toDir, "UniquePackages.manifest");
  209. // System.IO.File.Copy(fromPath, toPath);
  210. // EditorAssetInfo assetInfo = new EditorAssetInfo();
  211. // assetInfo.packageId = ManifestUtilities.MainAssetId;
  212. // assetInfo.path = System.IO.Path.Combine(ManifestUtilities.AssetManifestRelativePath, /*ManifestUtilities.UniquePackagesManifestFileName*/"UniquePackages.manifest").Replace('\\', '/');
  213. // assetInfos.Add(assetInfo.path, assetInfo);
  214. // Debug.Log($"GenerateUniquePackageManifest. assetInfo.path {assetInfo.path} , assetInfo {assetInfo.packageId}");
  215. // return manifest;
  216. //}
  217. //void GenerateAssetManifest(string outputDir, string streamingAssetsPath, ref Dictionary<string, EditorAssetInfo> assetInfos, CustomPackageInfo[] customPackageInfos)
  218. //{
  219. // List<AssetInfo> list = new List<AssetInfo>();
  220. // foreach (var assetInfo in assetInfos.Values)
  221. // {
  222. // bool isMainAsset = assetInfo.packageId == ManifestUtilities.MainAssetId || string.IsNullOrEmpty(assetInfo.packageId);
  223. // if (!isMainAsset) continue;
  224. // string path = GetOutputPath(outputDir, assetInfo.path, true, null);
  225. // AssetInfo info = new AssetInfo();
  226. // info.relativePath = assetInfo.path.Replace('\\', '/');
  227. // info.checkCodeType = ECheckCodeType.MD5;
  228. // info.size = new System.IO.FileInfo(path).Length;
  229. // info.checkCode = AssetUtilities.GetBinaryCheckCode(path, ECheckCodeType.MD5);
  230. // list.Add(info);
  231. // }
  232. // AssetManifest mainManifest = new AssetManifest();
  233. // mainManifest.assetInfos = list.ToArray();
  234. // string assetDir = System.IO.Path.Combine(outputDir, "packages", "main", "assets");
  235. // ManifestUtilities.SaveMainAssetManifest(assetDir, mainManifest);
  236. // string mainManifestFileName = $"{ManifestUtilities.MainAssetId}.{ManifestUtilities.ManifestExtensionName}";
  237. // string fromPath = System.IO.Path.Combine(assetDir, ManifestUtilities.AssetManifestRelativePath, mainManifestFileName);
  238. // string toDir = System.IO.Path.Combine(streamingAssetsPath, ManifestUtilities.AssetManifestRelativePath);
  239. // if (!System.IO.Directory.Exists(toDir)) System.IO.Directory.CreateDirectory(toDir);
  240. // string toPath = System.IO.Path.Combine(toDir, mainManifestFileName);
  241. // System.IO.File.Copy(fromPath, toPath);
  242. // EditorAssetInfo editorAssetInfo = new EditorAssetInfo();
  243. // editorAssetInfo.packageId = ManifestUtilities.MainAssetId;
  244. // editorAssetInfo.path = System.IO.Path.Combine(ManifestUtilities.AssetManifestRelativePath, mainManifestFileName);
  245. // assetInfos.Add(editorAssetInfo.path, editorAssetInfo);
  246. // if (null == customPackageInfos || customPackageInfos.Length <= 0) return;
  247. // foreach (var pkgInfo in customPackageInfos)
  248. // {
  249. // if ((null == pkgInfo.assetPaths || pkgInfo.assetPaths.Length <= 0) && (null == pkgInfo.dependencies || pkgInfo.dependencies.Length <= 0)) continue;
  250. // list.Clear();
  251. // foreach (var path in pkgInfo.assetPaths)
  252. // {
  253. // if (!assetInfos.TryGetValue(path, out var assetInfo))
  254. // {
  255. // BuildLog.Warn("Can't found asset: {0}, package: {1}", path, pkgInfo.packageID);
  256. // continue;
  257. // }
  258. // string outputPath = GetOutputPath(outputDir, assetInfo.path, false, pkgInfo.packageID);
  259. // AssetInfo info = new AssetInfo();
  260. // info.relativePath = assetInfo.path.Replace('\\', '/');
  261. // info.checkCodeType = ECheckCodeType.MD5;
  262. // info.size = new System.IO.FileInfo(outputPath).Length;
  263. // info.checkCode = AssetUtilities.GetBinaryCheckCode(outputPath, ECheckCodeType.MD5);
  264. // list.Add(info);
  265. // }
  266. // AssetManifest manifest = new AssetManifest();
  267. // manifest.assetInfos = list.ToArray();
  268. // assetDir = System.IO.Path.Combine(outputDir, "packages", pkgInfo.packageID, "assets");
  269. // ManifestUtilities.SaveExpansionAssetManifest(assetDir, pkgInfo.packageID, manifest);
  270. // editorAssetInfo = new EditorAssetInfo();
  271. // editorAssetInfo.packageId = pkgInfo.packageID;
  272. // editorAssetInfo.path = System.IO.Path.Combine(ManifestUtilities.AssetManifestRelativePath, $"{pkgInfo.packageID}.{ManifestUtilities.ManifestExtensionName}");
  273. // assetInfos.Add(editorAssetInfo.path, editorAssetInfo);
  274. // }
  275. //}
  276. //#endregion
  277. //#region generate backend-configs
  278. //void CollectPlacardAssets(HashSet<string> innerBundles, string dirPath, int platformTag, string streamAsstesDir, ref List<string> list)
  279. //{
  280. // var dirs = System.IO.Directory.GetDirectories(dirPath);
  281. // foreach (var dir in dirs)
  282. // {
  283. // var subPlatformTag = platformTag;
  284. // var entryPath = dir.Replace('\\', '/');
  285. // if (subPlatformTag != 1) subPlatformTag = KAFileUtil.VerifyPlatformPath(entryPath);
  286. // if (subPlatformTag == -1) continue;
  287. // CollectPlacardAssets(innerBundles, dir, platformTag, streamAsstesDir, ref list);
  288. // }
  289. // string[] files = System.IO.Directory.GetFiles(dirPath);
  290. // foreach (var file in files)
  291. // {
  292. // if (AssetUtilities.IsIgnorFile(file)) continue;
  293. // if (!(AssetUtilities.IsInnerAsset(file, AssetUtilities.PlacardTag) || innerBundles.Contains(file))) continue;
  294. // var entryPath = file.Replace('\\', '/');
  295. // string relativePath;
  296. // if (platformTag == 1)
  297. // {
  298. // //当前平台资源
  299. // var platformName = PlatformUtil.ActivePlatform.ToString();
  300. // relativePath = entryPath.Substring(entryPath.IndexOf(platformName) + platformName.Length + 1);
  301. // }
  302. // else
  303. // {
  304. // relativePath = entryPath.Substring(streamAsstesDir.Length + 1);
  305. // }
  306. // list.Add(relativePath);
  307. // }
  308. //}
  309. //void GeneratePlacardManifest(string backendConfigDir, ProductAssetsContext assetsContext)
  310. //{
  311. // var innerBundles = assetsContext.CollectPlacardBundles();
  312. // string streamAsstesDir = Kailash.Framework.Adapter.Driven.FileSystem.FileUtil.WorkPath.Replace('\\', '/');
  313. // List<string> placardAssets = new List<string>();
  314. // CollectPlacardAssets(innerBundles, streamAsstesDir, 0, streamAsstesDir, ref placardAssets);
  315. // List<PlacardInfo> placardInfos = new List<PlacardInfo>();
  316. // foreach (var item in placardAssets)
  317. // {
  318. // placardInfos.Add(new PlacardInfo() { filePath = item });
  319. // }
  320. // var manifest = new PlacardManifest();
  321. // manifest.placardInfos = placardInfos.ToArray();
  322. // string json = KailashJson.ToJson(manifest);
  323. // string path = System.IO.Path.Combine(backendConfigDir, "PlacardManifest.txt");
  324. // System.IO.File.WriteAllText(path, json);
  325. //}
  326. //void CalculateHotUpdateCheckCode(string outputDir, Dictionary<string, EditorAssetInfo> assetInfos)
  327. //{
  328. // var bundleCrcMap = CollectBundleCrc();
  329. // var regex = new Regex(@"CRC: (\d+)", RegexOptions.Multiline);
  330. // foreach (var item in assetInfos)
  331. // {
  332. // string ext = System.IO.Path.GetExtension(item.Key);
  333. // if (ext != ".bundle")
  334. // {
  335. // bool isMainAsset = item.Value.packageId == ManifestUtilities.MainAssetId || string.IsNullOrEmpty(item.Value.packageId);
  336. // string filePath = GetOutputPath(outputDir, item.Value.path, isMainAsset, item.Value.packageId);
  337. // item.Value.checkCode = KailashNative.GetMD5(filePath);
  338. // }
  339. // else
  340. // {
  341. // if (bundleCrcMap.TryGetValue(System.IO.Path.GetFileNameWithoutExtension(item.Key), out var bundleCrc))
  342. // {
  343. // item.Value.checkCode = bundleCrc;
  344. // }
  345. // else
  346. // {
  347. // string path = string.Format("{0}.manifest", item.Key);
  348. // if (System.IO.File.Exists(path))
  349. // {
  350. // string content = System.IO.File.ReadAllText(path);
  351. // var match = regex.Match(content);
  352. // item.Value.checkCode = match.Groups[1].Value;
  353. // }
  354. // else
  355. // {
  356. // BuildLog.Error($"CalculateHotUpdateCheckCode:找不到CRC配置信息。Path:{item.Key}");
  357. // }
  358. // }
  359. // }
  360. // }
  361. //}
  362. //#endregion
  363. string GetOutputPath(string outputDir, string relativePath, bool isMainAsset, string packageId)
  364. {
  365. return isMainAsset
  366. ? System.IO.Path.Combine(outputDir, "packages", "main", "assets", relativePath)
  367. : System.IO.Path.Combine(outputDir, "packages", packageId, "assets", relativePath);
  368. }
  369. BuildErrorCode ICommandExecuter.Execute()
  370. {
  371. var streamingAssetsPath = Application.streamingAssetsPath.Replace('\\', '/');
  372. if (System.IO.Directory.Exists(streamingAssetsPath))
  373. {
  374. UnityEditor.FileUtil.DeleteFileOrDirectory(streamingAssetsPath);
  375. UnityEditor.AssetDatabase.Refresh();
  376. }
  377. var pkgPath = System.IO.Path.Combine(Context.config.project.outputPath, "packages");
  378. if (System.IO.Directory.Exists(pkgPath))
  379. {
  380. UnityEditor.FileUtil.DeleteFileOrDirectory(pkgPath);
  381. }
  382. // 拷贝资源
  383. Dictionary<string, string> assetMap = AssetUtils.CollectionAllAssets();
  384. Dictionary<string, AbEncryptInfo> abEncryptInfos = CollectAbEncryptInfos();
  385. CopyAssets(streamingAssetsPath, assetMap, abEncryptInfos);
  386. //if (Context.config.editor.isNative)
  387. {
  388. //本地打包拷贝完资源即可退出
  389. UnityEditor.AssetDatabase.Refresh();
  390. return BuildErrorCode.CmdCompleted;
  391. }
  392. //var assetsContext = new ProductAssetsContext();
  393. //assetsContext.Init();
  394. //// 拆分分包资源
  395. //CollectionExpansionAssetInfos(assetsContext, assetMap, out Dictionary<string, EditorAssetInfo> assetInfos, out CustomPackageInfo[] customPackageInfos);
  396. //SplitAssets(Context.config.project.outputPath, streamingAssetsPath, assetInfos); // 移动或拷贝资源
  397. //// 生成专属包配置清单(Runtime):用于运行时,对分包资源进行操作
  398. //ExpansionPackageManifest manifest = GenerateUniquePackageManifest(Context.config.project.outputPath, streamingAssetsPath, customPackageInfos, ref assetInfos);
  399. //// 生成分包资源文件清单(包含主包)(Runtime):用于运行时,对分包资源进行校验
  400. //GenerateAssetManifest(Context.config.project.outputPath, streamingAssetsPath, ref assetInfos, customPackageInfos);
  401. //// 生成海报配置(Editor):用于制作更新包时,单独提取海报相关资源
  402. //string backendConfigDir = System.IO.Path.Combine(Context.config.project.outputPath, "backend-configs");
  403. //if (!System.IO.Directory.Exists(backendConfigDir)) System.IO.Directory.CreateDirectory(backendConfigDir);
  404. //GeneratePlacardManifest(backendConfigDir, assetsContext);
  405. //// 生成专属包配置清单(Editor):用于上传分包时,上传相关的分包信息
  406. //string json = XJson.ToJson(manifest);
  407. //string path = System.IO.Path.Combine(backendConfigDir, "UniquePackages.txt");
  408. //System.IO.File.WriteAllText(path, json);
  409. //// 生成所有资源清单:用于制作更新包时,对资源进行对比
  410. //CalculateHotUpdateCheckCode(Context.config.project.outputPath, assetInfos);
  411. //List<EditorAssetInfo> infos = new List<EditorAssetInfo>();
  412. //foreach (var info in assetInfos.Values)
  413. //{
  414. // infos.Add(info);
  415. //}
  416. //EditorAssetInfoManifest editorAssetInfoManifest = new EditorAssetInfoManifest();
  417. //editorAssetInfoManifest.assetInfos = infos.ToArray();
  418. //json = XJson.ToJson(editorAssetInfoManifest);
  419. //path = System.IO.Path.Combine(backendConfigDir, "AssetsManifest.txt");
  420. //System.IO.File.WriteAllText(path, json);
  421. ////由于分包会将资源从streamingAssetsPath移出,因此在最后才调用Refresh()
  422. //UnityEditor.AssetDatabase.Refresh();
  423. //return BuildErrorCode.CmdCompleted;
  424. }
  425. }
  426. }