CodeLoader.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. using Cysharp.Threading.Tasks;
  2. using HybridCLR;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.IO;
  7. using System.Reflection;
  8. using UnityEngine;
  9. using YooAsset;
  10. namespace ET
  11. {
  12. public class CodeLoader: Singleton<CodeLoader>
  13. {
  14. public void Start()
  15. {
  16. if (Define.EnableCodes)
  17. {
  18. GlobalConfig globalConfig = Resources.Load<GlobalConfig>("GlobalConfig");
  19. if (globalConfig.CodeMode != CodeMode.ClientServer)
  20. {
  21. throw new Exception("ENABLE_CODES mode must use ClientServer code mode!");
  22. }
  23. Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
  24. Dictionary<string, Type> types = AssemblyHelper.GetAssemblyTypes(assemblies);
  25. EventSystem.Instance.Add(types);
  26. bool bStart = false;
  27. foreach (Assembly ass in assemblies)
  28. {
  29. string name = ass.GetName().Name;
  30. if (name == "Unity.Model.Codes")
  31. {
  32. //this.model = ass;
  33. bStart= true;
  34. IStaticMethod start = new StaticMethod(ass, "ET.Entry", "Start");
  35. start.Run();
  36. break;
  37. }
  38. }
  39. if(!bStart)
  40. {
  41. throw new Exception("not found Assembly: 'Unity.Model.Codes'");
  42. }
  43. }
  44. else
  45. {
  46. LoadHotfix();
  47. }
  48. }
  49. //编译时会检查这个方法,需保留
  50. public void LoadHotfix()
  51. {
  52. AsyncLoadHotfix().Forget();
  53. }
  54. private async UniTaskVoid AsyncLoadHotfix()
  55. {
  56. GlobalConfig globalConfig = Resources.Load<GlobalConfig>("GlobalConfig");
  57. Log.Info($"start mode: {globalConfig.PlayMode}");
  58. // 启动YooAsset引擎,并在初始化完毕后进行热更代码加载
  59. await YooAssetProxy.StartYooAssetEngine(globalConfig.PlayMode);
  60. // Shader Warm Up
  61. ShaderVariantCollection shaderVariantCollection =
  62. (await YooAssetProxy.LoadAssetAsync<ShaderVariantCollection>(
  63. YooAssetProxy.GetYooAssetFormatResPath("ProjectSShaderVariant",
  64. YooAssetProxy.YooAssetResType.Shader)))
  65. .GetAssetObject<ShaderVariantCollection>();
  66. Stopwatch stopwatch = Stopwatch.StartNew();
  67. shaderVariantCollection.WarmUp();
  68. stopwatch.Stop();
  69. Log.Info($"Shader Warm Up完成, 耗时: {stopwatch.ElapsedMilliseconds}ms,shaderCount: {shaderVariantCollection.shaderCount} variantCount: {shaderVariantCollection.variantCount}");
  70. //给mscorlib.dll等AOT补充元数据
  71. await LoadMetadataForAOT();
  72. await LoadHotfixCode();
  73. }
  74. // 加载assembly对应的dll,会自动为它hook。一旦aot泛型函数的native函数不存在,用解释器版本代码
  75. private async UniTask LoadMetadataForAOT()
  76. {
  77. //AOT dll列表的配置也可以通过热更新下下来,这样增加了新的泛型就不怕了
  78. HotUpdateAssemblyManifest mainfest =
  79. (await YooAssetProxy.LoadAssetAsync<HotUpdateAssemblyManifest>("HotUpdateAssemblyManifest"))
  80. .GetAssetObject<HotUpdateAssemblyManifest>();
  81. var DLLNameList_ForABLoad = mainfest.AOTMetadataDlls;
  82. List<UniTask<RawFileOperation>> tasks = new List<UniTask<RawFileOperation>>();
  83. foreach (var aotDll in DLLNameList_ForABLoad)
  84. {
  85. tasks.Add(YooAssetProxy.GetRawFileAsync(aotDll));
  86. }
  87. RawFileOperation[] rawFileOperations = await UniTask.WhenAll(tasks);
  88. foreach (var task in rawFileOperations)
  89. {
  90. var ret = RuntimeApi.LoadMetadataForAOTAssembly(task.GetRawBytes(), HomologousImageMode.SuperSet);
  91. if (ret == LoadImageErrorCode.OK)
  92. {
  93. Log.Debug($"LoadMetadataForAOTAssembly({task.GetBundleName()}) ok.");
  94. }
  95. else
  96. {
  97. Log.Error($"LoadMetadataForAOTAssembly({task.GetBundleName()}) Error: {ret}");
  98. }
  99. }
  100. }
  101. //热更加载 model.dll & hotfix.dll
  102. private async UniTask LoadHotfixCode()
  103. {
  104. Log.Info("to load model.dll & hotfix.dll.");
  105. var rawfile_modeldll = await YooAssetProxy.GetRawFileAsync("Model.dll");
  106. var rawfile_modelpdb = await YooAssetProxy.GetRawFileAsync("Model.pdb");
  107. var modelAssembly = Assembly.Load(rawfile_modeldll.GetRawBytes(), rawfile_modelpdb.GetRawBytes());
  108. var rawfile_hotfixdll = await YooAssetProxy.GetRawFileAsync("Hotfix.dll");
  109. var rawfile_hotfixpdb = await YooAssetProxy.GetRawFileAsync("Hotfix.pdb");
  110. var hotfixAssembly = Assembly.Load(rawfile_hotfixdll.GetRawBytes(), rawfile_hotfixpdb.GetRawBytes());
  111. Dictionary<string, Type> types = AssemblyHelper.GetAssemblyTypes(typeof(Game).Assembly, typeof(Init).Assembly, modelAssembly, hotfixAssembly);
  112. EventSystem.Instance.Add(types);
  113. Log.Info("to call Client.Entry.");
  114. IStaticMethod start = new MonoStaticMethod(modelAssembly, "ET.Entry", "Start");
  115. start.Run();
  116. }
  117. }
  118. }