CompileScriptsHandle.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. using XGame.Editor.Build;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Text.RegularExpressions;
  6. using UnityEditor;
  7. using UnityEditor.Compilation;
  8. using UnityEngine;
  9. using XGame.Framework.Json;
  10. namespace XGame.Editor.Compiler
  11. {
  12. //[InitializeOnLoad]
  13. public static class CompileScriptsHandle
  14. {
  15. private static CompileResult result;
  16. [UnityEditor.Callbacks.DidReloadScripts]
  17. static void OnDidReloadScripts()
  18. {
  19. //Debug.Log("CompileScriptsHandle OnDidReloadScripts.");
  20. EditorApplication.quitting -= OnQuit;
  21. EditorApplication.quitting += OnQuit;
  22. CompilationPipeline.compilationFinished -= OnCompilationFinished;
  23. CompilationPipeline.compilationFinished += OnCompilationFinished;
  24. CompilationPipeline.assemblyCompilationFinished -= OnAssemblyCompilationFinished;
  25. CompilationPipeline.assemblyCompilationFinished += OnAssemblyCompilationFinished;
  26. //加载 初始化ICompileEvents
  27. if (HasEvents)
  28. {
  29. EditorApplication.update += OnUpdate;
  30. }
  31. //Debug.Log($"CompileScriptsHandle InitializeOnLoad. isCompiling: {EditorApplication.isCompiling}");
  32. }
  33. //[InitializeOnLoadMethod]
  34. //static void OnInitializeOnLoadMethod()
  35. //{
  36. // Debug.Log("CompileScriptsHandle OnInitializeOnLoadMethod.");
  37. //}
  38. /// <summary>
  39. /// 监听编辑器退出事件
  40. /// </summary>
  41. private static void OnQuit()
  42. {
  43. //Debug.Log("EditorApplication OnQuit.");
  44. Clear();
  45. }
  46. /// <summary>
  47. /// 监听Assembly编译事件
  48. /// 编译失败时需要记录失败状态
  49. /// </summary>
  50. /// <param name="obj"></param>
  51. /// <param name="messages"></param>
  52. private static void OnAssemblyCompilationFinished(string obj, CompilerMessage[] messages)
  53. {
  54. //Debug.Log($"OnAssemblyCompilationFinished. obj:{obj?.ToString() ?? "null"} msgCount:{messages?.Length ?? 0}");
  55. if (messages != null && HasEvents)
  56. {
  57. foreach(var msg in messages)
  58. {
  59. if (msg.type == CompilerMessageType.Error)
  60. {
  61. result.isFailed = true;
  62. result.message = msg.message;
  63. if (result.isCopyAssemblyFailed == false && msg.message.Contains("Copying assembly from"))
  64. {
  65. //assembly拷贝失败
  66. result.isCopyAssemblyFailed = true;
  67. }
  68. //打印错误信息
  69. BuildLog.Error($"OnAssemblyCompilation error. msg:{msg.message} file:{msg.file} line:{msg.line} col:{msg.column}");
  70. }
  71. }
  72. }
  73. }
  74. /// <summary>
  75. /// 监听编译结束回调事件
  76. /// 编译失败时 Unity 不会执行InitializeOnLoad
  77. /// 需要主动执行回调事件
  78. /// </summary>
  79. /// <param name="obj"></param>
  80. private static void OnCompilationFinished(object obj)
  81. {
  82. //Debug.Log($"OnCompilationFinished. obj:{obj?.ToString() ?? "null"}");
  83. if (result.isFailed == false) return;
  84. //编译失败,主动执行回调
  85. if (HasEvents)
  86. {
  87. EditorApplication.update += OnUpdate;
  88. }
  89. }
  90. private static void OnUpdate()
  91. {
  92. //Debug.Log($"CompileScriptsHandle OnUpdate. isCompiling: {EditorApplication.isCompiling} isFailed:{result.isFailed}");
  93. EditorApplication.update -= OnUpdate;
  94. if (UnityEditorInternal.InternalEditorUtility.inBatchMode == false && result.isFailed && result.isCopyAssemblyFailed)
  95. {
  96. //非BatchMode下, 编译失败,并且是拷贝Assembly失败,重新编译
  97. BuildLog.Log($"Compile Scripts Error: Assembly copy failed. Restart RequestScriptCompilation.");
  98. result = default;
  99. CompilationPipeline.RequestScriptCompilation();
  100. return;
  101. }
  102. var events = ReadEvents();
  103. if (events != null)
  104. {
  105. var tempResult = result;
  106. result = default;
  107. for (int i = 0; i < events.Length; i++)
  108. {
  109. if (tempResult.isFailed)
  110. {
  111. events[i].OnCompileFailed(tempResult);
  112. }
  113. else
  114. {
  115. events[i].OnCompileSuccess();
  116. }
  117. }
  118. events = null;
  119. }
  120. }
  121. private static string OutputPath
  122. {
  123. get
  124. {
  125. return Path.GetFullPath($"{Application.dataPath}/../ExtAssets/Editor/CompileEvents.json").Replace("\\", "/");
  126. }
  127. }
  128. /// <summary>
  129. /// 是否有监听事件
  130. /// </summary>
  131. private static bool HasEvents => File.Exists(OutputPath);
  132. public static void RegistEvent(ICompileEvent compileEvent)
  133. {
  134. var filePath = OutputPath;
  135. var dir = Path.GetDirectoryName(filePath);
  136. if (!Directory.Exists(dir))
  137. {
  138. Directory.CreateDirectory(dir);
  139. }
  140. var str = $"<type:{compileEvent.GetType().AssemblyQualifiedName} value:{XJson.ToJson(compileEvent)}/>";
  141. try
  142. {
  143. var writer = File.Exists(filePath) ? new StreamWriter(filePath, true) : new StreamWriter(filePath);
  144. writer.WriteLine(str);
  145. writer.Flush();
  146. writer.Close();
  147. BuildLog.Log($"CompileScriptsHandle RegistEvent:{str}");
  148. }
  149. catch (Exception ex)
  150. {
  151. BuildLog.Exception(ex);
  152. }
  153. }
  154. private static ICompileEvent[] ReadEvents()
  155. {
  156. var path = OutputPath;
  157. if (File.Exists(path))
  158. {
  159. List<ICompileEvent> lst = new List<ICompileEvent>();
  160. try
  161. {
  162. Regex regex = new Regex(@"<type:(.+?) value:(.+?)/>", RegexOptions.Multiline);
  163. var lines = File.ReadAllLines(path);
  164. foreach (var line in lines)
  165. {
  166. var match = regex.Match(line);
  167. if (match.Success)
  168. {
  169. var typeName = match.Groups[1].Value;
  170. var eventValue = match.Groups[2].Value;
  171. BuildLog.Log($"CompileScriptsHandle ReadEvents type:{typeName} value:{eventValue}");
  172. Type type = Type.GetType(typeName);
  173. var compileEvent = XJson.ToObject(eventValue, type) as ICompileEvent;
  174. lst.Add(compileEvent);
  175. }
  176. }
  177. lst.Sort((a, b) =>
  178. {
  179. return a.Priority - b.Priority;
  180. });
  181. }
  182. catch (Exception ex)
  183. {
  184. BuildLog.Exception(ex);
  185. }
  186. //删除文件
  187. Clear();
  188. return lst.ToArray();
  189. }
  190. return null;
  191. }
  192. public static void Clear()
  193. {
  194. var path = OutputPath;
  195. if (File.Exists(path))
  196. {
  197. File.Delete(path);
  198. }
  199. }
  200. }
  201. }