CompileScriptsHandle.cs 7.7 KB

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