BuildProcessor_2019.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #if UNITY_2018_1_OR_NEWER && !UNITY_2020_1_OR_NEWER
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEditor;
  5. using UnityEditor.Build;
  6. using UnityEditor.Build.Reporting;
  7. using UnityEngine;
  8. using UnityEngine.SceneManagement;
  9. using System.Linq;
  10. using System.IO;
  11. using System;
  12. using UnityEditor.UnityLinker;
  13. using System.Reflection;
  14. using UnityEditor.Il2Cpp;
  15. using HybridCLR.Editor.GlobalManagers;
  16. #if UNITY_ANDROID
  17. using UnityEditor.Android;
  18. #endif
  19. namespace HybridCLR
  20. {
  21. public class BuildProcessor_2019 : IPreprocessBuildWithReport, IPostprocessBuildWithReport
  22. #if UNITY_ANDROID
  23. , IPostGenerateGradleAndroidProject
  24. #endif
  25. , IProcessSceneWithReport, IFilterBuildAssemblies, IPostBuildPlayerScriptDLLs, IUnityLinkerProcessor, IIl2CppProcessor
  26. {
  27. /// <summary>
  28. /// 需要在Prefab上挂脚本的热更dll名称列表,不需要挂到Prefab上的脚本可以不放在这里
  29. /// 但放在这里的dll即使勾选了 AnyPlatform 也会在打包过程中被排除
  30. ///
  31. /// 另外请务必注意!: 需要挂脚本的dll的名字最好别改,因为这个列表无法热更(上线后删除或添加某些非挂脚本dll没问题)
  32. /// </summary>
  33. static List<string> monoDllNames = new List<string>() { "HotFix.dll"};
  34. static MethodInfo s_BuildReport_AddMessage;
  35. int IOrderedCallback.callbackOrder => 0;
  36. static BuildProcessor_2019()
  37. {
  38. s_BuildReport_AddMessage = typeof(BuildReport).GetMethod("AddMessage", BindingFlags.Instance | BindingFlags.NonPublic);
  39. }
  40. void IPreprocessBuildWithReport.OnPreprocessBuild(BuildReport report)
  41. {
  42. if (!Application.isBatchMode && !EditorUtility.DisplayDialog("确认", "建议 Build 之前先打包 AssetBundle\r\n是否继续?", "继续", "取消"))
  43. {
  44. s_BuildReport_AddMessage.Invoke(report, new object[] { LogType.Exception, "用户取消", "BuildFailedException" });
  45. return;
  46. }
  47. }
  48. string[] IFilterBuildAssemblies.OnFilterAssemblies(BuildOptions buildOptions, string[] assemblies)
  49. {
  50. // 将热更dll从打包列表中移除
  51. List<string> newNames = new List<string>(assemblies.Length);
  52. foreach(string assembly in assemblies)
  53. {
  54. bool found = false;
  55. foreach(string removeName in monoDllNames)
  56. {
  57. if(assembly.EndsWith(removeName, StringComparison.OrdinalIgnoreCase))
  58. {
  59. found = true;
  60. break;
  61. }
  62. }
  63. if(!found)
  64. newNames.Add(assembly);
  65. }
  66. return newNames.ToArray();
  67. }
  68. [Serializable]
  69. public class ScriptingAssemblies
  70. {
  71. public List<string> names;
  72. public List<int> types;
  73. }
  74. void IPostprocessBuildWithReport.OnPostprocessBuild(BuildReport report)
  75. {
  76. AddBackHotFixAssembliesTo_BinFile(report, null);
  77. }
  78. #if UNITY_ANDROID
  79. void IPostGenerateGradleAndroidProject.OnPostGenerateGradleAndroidProject(string path)
  80. {
  81. // 由于 Android 平台在 OnPostprocessBuild 调用时已经生成完 apk 文件,因此需要提前调用
  82. AddBackHotFixAssembliesTo_BinFile(null, path);
  83. }
  84. #endif
  85. private void AddBackHotFixAssembliesTo_BinFile(BuildReport report, string path)
  86. {
  87. /*
  88. * Unity2019 中 dll 加载列表存储在 globalgamemanagers 文件中,此列表在游戏启动时自动加载,
  89. * 不在此列表中的dll在资源反序列化时无法被找到其类型
  90. * 因此 OnFilterAssemblies 中移除的条目需要再加回来
  91. */
  92. #if UNITY_ANDROID
  93. string[] binFiles = new string[] { "Temp/gradleOut/unityLibrary/src/main/assets/bin/Data/globalgamemanagers" }; // report.files 不包含 Temp/gradleOut 等目录
  94. #else
  95. // 直接出包和输出vs工程时路径不同,report.summary.outputPath 记录的是前者路径
  96. string[] binFiles = Directory.GetFiles(Path.GetDirectoryName(report.summary.outputPath), "globalgamemanagers", SearchOption.AllDirectories);
  97. #endif
  98. if (binFiles.Length == 0)
  99. {
  100. Debug.LogError("can not find file ScriptingAssemblies.json");
  101. return;
  102. }
  103. foreach (string binPath in binFiles)
  104. {
  105. var binFile = new UnityBinFile();
  106. binFile.LoadFromFile(binPath);
  107. ScriptsData scriptsData = binFile.scriptsData;
  108. foreach (string name in monoDllNames)
  109. {
  110. if(!scriptsData.dllNames.Contains(name))
  111. {
  112. scriptsData.dllNames.Add(name);
  113. scriptsData.dllTypes.Add(16); // user dll type
  114. }
  115. }
  116. binFile.scriptsData = scriptsData;
  117. binFile.RebuildAndFlushToFile(binPath);
  118. }
  119. }
  120. void IProcessSceneWithReport.OnProcessScene(Scene scene, BuildReport report)
  121. {
  122. }
  123. void IPostBuildPlayerScriptDLLs.OnPostBuildPlayerScriptDLLs(BuildReport report)
  124. {
  125. }
  126. string IUnityLinkerProcessor.GenerateAdditionalLinkXmlFile(BuildReport report, UnityLinkerBuildPipelineData data)
  127. {
  128. return String.Empty;
  129. }
  130. void IUnityLinkerProcessor.OnBeforeRun(BuildReport report, UnityLinkerBuildPipelineData data)
  131. {
  132. }
  133. void IUnityLinkerProcessor.OnAfterRun(BuildReport report, UnityLinkerBuildPipelineData data)
  134. {
  135. }
  136. void IIl2CppProcessor.OnBeforeConvertRun(BuildReport report, Il2CppBuildPipelineData data)
  137. {
  138. }
  139. #if UNITY_IOS
  140. // hook UnityEditor.BuildCompletionEventsHandler.ReportPostBuildCompletionInfo() ? 因为没有 mac 打包平台因此不清楚
  141. #endif
  142. }
  143. }
  144. #endif