PatchScriptingAssemblyList.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. using HybridCLR.Editor.UnityBinFileReader;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using UnityEditor;
  9. using UnityEditor.Android;
  10. using UnityEditor.Build;
  11. using UnityEditor.Build.Reporting;
  12. using UnityEditor.UnityLinker;
  13. using UnityEngine;
  14. using UnityFS;
  15. #if !UNITY_2023_1_OR_NEWER
  16. using UnityEditor.Il2Cpp;
  17. #endif
  18. namespace HybridCLR.Editor.BuildProcessors
  19. {
  20. public class PatchScriptingAssemblyList :
  21. #if UNITY_ANDROID
  22. IPostGenerateGradleAndroidProject,
  23. #elif UNITY_OPENHARMONY
  24. UnityEditor.OpenHarmony.IPostGenerateOpenHarmonyProject,
  25. #endif
  26. IPostprocessBuildWithReport
  27. #if !UNITY_2021_1_OR_NEWER && UNITY_WEBGL
  28. , IIl2CppProcessor
  29. #endif
  30. #if UNITY_PS5
  31. , IUnityLinkerProcessor
  32. #endif
  33. {
  34. public int callbackOrder => 0;
  35. public void OnPostGenerateGradleAndroidProject(string path)
  36. {
  37. // 如果直接打包apk,没有机会在PostprocessBuild中修改ScriptingAssemblies.json。
  38. // 因此需要在这个时机处理
  39. // Unity有bug,偶然情况下会传入apk的路径,导致替换失败
  40. if (Directory.Exists(path))
  41. {
  42. PathScriptingAssembilesFile(path);
  43. }
  44. else
  45. {
  46. PathScriptingAssembilesFile($"{SettingsUtil.ProjectDir}/Library");
  47. }
  48. }
  49. #if UNITY_OPENHARMONY
  50. public void OnPostGenerateOpenHarmonyProject(string path)
  51. {
  52. OnPostGenerateGradleAndroidProject(path);
  53. }
  54. #endif
  55. public void OnPostprocessBuild(BuildReport report)
  56. {
  57. // 如果target为Android,由于已经在OnPostGenerateGradelAndroidProject中处理过,
  58. // 这里不再重复处理
  59. #if !UNITY_ANDROID && !UNITY_WEBGL && !UNITY_OPENHARMONY
  60. PathScriptingAssembilesFile(report.summary.outputPath);
  61. #endif
  62. }
  63. #if UNITY_PS5
  64. /// <summary>
  65. /// 打包模式如果是 Package 需要在这个阶段提前处理 .json , PC Hosted 和 GP5 模式不受影响
  66. /// </summary>
  67. public string GenerateAdditionalLinkXmlFile(UnityEditor.Build.Reporting.BuildReport report, UnityEditor.UnityLinker.UnityLinkerBuildPipelineData data)
  68. {
  69. string path = $"{SettingsUtil.ProjectDir}/Library/PlayerDataCache/PS5/Data";
  70. PathScriptingAssembilesFile(path);
  71. return null;
  72. }
  73. #endif
  74. public void PathScriptingAssembilesFile(string path)
  75. {
  76. if (!SettingsUtil.Enable)
  77. {
  78. Debug.Log($"[PatchScriptingAssemblyList] disabled");
  79. return;
  80. }
  81. Debug.Log($"[PatchScriptingAssemblyList]. path:{path}");
  82. if (!Directory.Exists(path))
  83. {
  84. path = Path.GetDirectoryName(path);
  85. Debug.Log($"[PatchScriptingAssemblyList] get path parent:{path}");
  86. }
  87. #if UNITY_2020_1_OR_NEWER
  88. AddHotFixAssembliesToScriptingAssembliesJson(path);
  89. #else
  90. AddHotFixAssembliesToBinFile(path);
  91. #endif
  92. }
  93. private void AddHotFixAssembliesToScriptingAssembliesJson(string path)
  94. {
  95. Debug.Log($"[PatchScriptingAssemblyList]. path:{path}");
  96. /*
  97. * ScriptingAssemblies.json 文件中记录了所有的dll名称,此列表在游戏启动时自动加载,
  98. * 不在此列表中的dll在资源反序列化时无法被找到其类型
  99. * 因此 OnFilterAssemblies 中移除的条目需要再加回来
  100. */
  101. string[] jsonFiles = Directory.GetFiles(path, SettingsUtil.ScriptingAssembliesJsonFile, SearchOption.AllDirectories);
  102. if (jsonFiles.Length == 0)
  103. {
  104. Debug.LogWarning($"can not find file {SettingsUtil.ScriptingAssembliesJsonFile}");
  105. return;
  106. }
  107. foreach (string file in jsonFiles)
  108. {
  109. var patcher = new ScriptingAssembliesJsonPatcher();
  110. patcher.Load(file);
  111. patcher.AddScriptingAssemblies(SettingsUtil.HotUpdateAssemblyFilesIncludePreserved);
  112. patcher.Save(file);
  113. }
  114. }
  115. private void AddHotFixAssembliesToBinFile(string path)
  116. {
  117. #if UNITY_STANDALONE_OSX
  118. path = Path.GetDirectoryName(path);
  119. #endif
  120. if (AddHotFixAssembliesToGlobalgamemanagers(path))
  121. {
  122. return;
  123. }
  124. if (AddHotFixAssembliesTodataunity3d(path))
  125. {
  126. return;
  127. }
  128. Debug.LogError($"[PatchScriptingAssemblyList] can not find file '{SettingsUtil.GlobalgamemanagersBinFile}' or '{SettingsUtil.Dataunity3dBinFile}' in '{path}'");
  129. }
  130. private bool AddHotFixAssembliesToGlobalgamemanagers(string path)
  131. {
  132. string[] binFiles = Directory.GetFiles(path, SettingsUtil.GlobalgamemanagersBinFile, SearchOption.AllDirectories);
  133. if (binFiles.Length == 0)
  134. {
  135. return false;
  136. }
  137. foreach (string binPath in binFiles)
  138. {
  139. var binFile = new UnityBinFile();
  140. binFile.Load(binPath);
  141. binFile.AddScriptingAssemblies(SettingsUtil.HotUpdateAssemblyFilesIncludePreserved);
  142. binFile.Save(binPath);
  143. Debug.Log($"[PatchScriptingAssemblyList] patch {binPath}");
  144. }
  145. return true;
  146. }
  147. private bool AddHotFixAssembliesTodataunity3d(string path)
  148. {
  149. string[] binFiles = Directory.GetFiles(path, SettingsUtil.Dataunity3dBinFile, SearchOption.AllDirectories);
  150. if (binFiles.Length == 0)
  151. {
  152. return false;
  153. }
  154. foreach (string binPath in binFiles)
  155. {
  156. var patcher = new Dataunity3dPatcher();
  157. patcher.ApplyPatch(binPath, SettingsUtil.HotUpdateAssemblyFilesIncludePreserved);
  158. Debug.Log($"[PatchScriptingAssemblyList] patch {binPath}");
  159. }
  160. return true;
  161. }
  162. #if UNITY_WEBGL && !UNITY_2022_3_OR_NEWER
  163. public void OnBeforeConvertRun(BuildReport report, Il2CppBuildPipelineData data)
  164. {
  165. PathScriptingAssembilesFile($"{SettingsUtil.ProjectDir}/Temp/StagingArea/Data");
  166. }
  167. #endif
  168. }
  169. }