CodeLoader.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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. private Assembly model;
  15. public void Start()
  16. {
  17. if (Define.EnableCodes)
  18. {
  19. GlobalConfig globalConfig = Resources.Load<GlobalConfig>("GlobalConfig");
  20. if (globalConfig.CodeMode != CodeMode.ClientServer)
  21. {
  22. throw new Exception("ENABLE_CODES mode must use ClientServer code mode!");
  23. }
  24. Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
  25. Dictionary<string, Type> types = AssemblyHelper.GetAssemblyTypes(assemblies);
  26. EventSystem.Instance.Add(types);
  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. }
  34. }
  35. IStaticMethod start = new StaticMethod(this.model, "ET.Entry", "Start");
  36. start.Run();
  37. }
  38. else
  39. {
  40. LoadAssetsAndHotfix().Forget();
  41. }
  42. }
  43. private async UniTaskVoid LoadAssetsAndHotfix()
  44. {
  45. // 启动YooAsset引擎,并在初始化完毕后进行热更代码加载
  46. await YooAssetProxy.StartYooAssetEngine(YooAssets.EPlayMode.HostPlayMode);
  47. // Shader Warm Up
  48. /*ShaderVariantCollection shaderVariantCollection =
  49. (await YooAssetProxy.LoadAssetAsync<ShaderVariantCollection>(
  50. YooAssetProxy.GetYooAssetFormatResPath("ProjectSShaderVariant",
  51. YooAssetProxy.YooAssetResType.Shader)))
  52. .GetAssetObject<ShaderVariantCollection>();
  53. Stopwatch stopwatch = Stopwatch.StartNew();
  54. shaderVariantCollection.WarmUp();
  55. stopwatch.Stop();
  56. Log.Info($"Shader Warm Up完成, 耗时: {stopwatch.ElapsedMilliseconds}ms,shaderCount: {shaderVariantCollection.shaderCount} variantCount: {shaderVariantCollection.variantCount}");*/
  57. #if !UNITY_EDITOR
  58. //给mscorlib.dll等AOT补充元数据
  59. await LoadMetadataForAOT();
  60. #endif
  61. await LoadHotfixCode();
  62. }
  63. // 加载assembly对应的dll,会自动为它hook。一旦aot泛型函数的native函数不存在,用解释器版本代码
  64. private async UniTask LoadMetadataForAOT()
  65. {
  66. //TODO: DLL列表
  67. List<string> DLLNameList_ForABLoad = new List<string> (){ } ;
  68. List<UniTask<RawFileOperation>> tasks = new List<UniTask<RawFileOperation>>();
  69. foreach (var aotDll in DLLNameList_ForABLoad)
  70. {
  71. tasks.Add(YooAssetProxy.GetRawFileAsync(aotDll));
  72. }
  73. RawFileOperation[] rawFileOperations = await UniTask.WhenAll(tasks);
  74. foreach (var task in rawFileOperations)
  75. {
  76. var ret = RuntimeApi.LoadMetadataForAOTAssembly(task.GetRawBytes(), HomologousImageMode.SuperSet);
  77. if (ret == LoadImageErrorCode.OK)
  78. {
  79. Log.Info($"LoadMetadataForAOTAssembly({task.GetBundleName()}) ok.");
  80. }
  81. else
  82. {
  83. Log.Error($"LoadMetadataForAOTAssembly({task.GetBundleName()}) Error: {ret}");
  84. }
  85. }
  86. }
  87. //TODO: load model.dll hotfix.dll
  88. public async UniTask LoadHotfixCode()
  89. {
  90. Log.Info("to load hotfix.dll.");
  91. byte[] assBytes = (await YooAssetProxy.GetRawFileAsync("Code_ProjectS_Hotfix.dll")).GetRawBytes();
  92. byte[] pdbBytes = (await YooAssetProxy.GetRawFileAsync("Code_ProjectS_Hotfix.pdb")).GetRawBytes();
  93. var assembly = Assembly.Load(assBytes, pdbBytes);
  94. //Dictionary<string, Type> types = AssemblyHelper.GetAssemblyTypes(typeof(Game).Assembly, typeof(Init).Assembly, this.model, hotfixAssembly);
  95. //EventSystem.Instance.Add(types);
  96. Log.Info("to call Client.Entry.");
  97. IStaticMethod start = new MonoStaticMethod(assembly, "ET.Client.Entry", "Start");
  98. start.Run();
  99. }
  100. }
  101. }