LoadDll.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. using HybridCLR;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Reflection;
  8. using System.Threading.Tasks;
  9. using UnityEngine;
  10. using UnityEngine.Networking;
  11. public class LoadDll : MonoBehaviour
  12. {
  13. static LoadDll instance;
  14. private void Awake()
  15. {
  16. instance = this;
  17. }
  18. void Start()
  19. {
  20. StartCoroutine(DownLoadAssets(this.StartGame));
  21. }
  22. #region download assets
  23. private static Dictionary<string, byte[]> s_assetDatas = new Dictionary<string, byte[]>();
  24. public static byte[] ReadBytesFromStreamingAssets(string dllName)
  25. {
  26. return s_assetDatas[dllName];
  27. }
  28. private string GetWebRequestPath(string asset)
  29. {
  30. var path = $"{Application.streamingAssetsPath}/{asset}";
  31. if (!path.Contains("://"))
  32. {
  33. path = "file://" + path;
  34. }
  35. return path;
  36. }
  37. private static List<string> AOTMetaAssemblyFiles { get; } = new List<string>()
  38. {
  39. "mscorlib.dll.bytes",
  40. "System.dll.bytes",
  41. "System.Core.dll.bytes",
  42. };
  43. IEnumerator DownLoadAssets(Action onDownloadComplete)
  44. {
  45. var assets = new List<string>
  46. {
  47. "playsounds",
  48. "excel_buttom",
  49. "gongye",
  50. "prefabs",
  51. "cubetest",
  52. "HotUpdate.dll.bytes",
  53. }.Concat(AOTMetaAssemblyFiles);
  54. foreach (var asset in assets)
  55. {
  56. string dllPath = GetWebRequestPath(asset);
  57. Debug.Log($"start download asset:{dllPath}");
  58. UnityWebRequest www = UnityWebRequest.Get(dllPath);
  59. yield return www.SendWebRequest();
  60. #if UNITY_2020_1_OR_NEWER
  61. if (www.result != UnityWebRequest.Result.Success)
  62. {
  63. Debug.Log(www.error);
  64. }
  65. #else
  66. if (www.isHttpError || www.isNetworkError)
  67. {
  68. Debug.Log(www.error);
  69. }
  70. #endif
  71. else
  72. {
  73. // Or retrieve results as binary data
  74. byte[] assetData = www.downloadHandler.data;
  75. Debug.Log($"dll:{asset} size:{assetData.Length}");
  76. s_assetDatas[asset] = assetData;
  77. }
  78. }
  79. onDownloadComplete();
  80. }
  81. #endregion
  82. private static Assembly _hotUpdateAss;
  83. /// <summary>
  84. /// 为aot assembly加载原始metadata, 这个代码放aot或者热更新都行。
  85. /// 一旦加载后,如果AOT泛型函数对应native实现不存在,则自动替换为解释模式执行
  86. /// </summary>
  87. private static void LoadMetadataForAOTAssemblies()
  88. {
  89. /// 注意,补充元数据是给AOT dll补充元数据,而不是给热更新dll补充元数据。
  90. /// 热更新dll不缺元数据,不需要补充,如果调用LoadMetadataForAOTAssembly会返回错误
  91. ///
  92. HomologousImageMode mode = HomologousImageMode.SuperSet;
  93. foreach (var aotDllName in AOTMetaAssemblyFiles)
  94. {
  95. byte[] dllBytes = ReadBytesFromStreamingAssets(aotDllName);
  96. // 加载assembly对应的dll,会自动为它hook。一旦aot泛型函数的native函数不存在,用解释器版本代码
  97. LoadImageErrorCode err = RuntimeApi.LoadMetadataForAOTAssembly(dllBytes, mode);
  98. Debug.Log($"LoadMetadataForAOTAssembly:{aotDllName}. mode:{mode} ret:{err}");
  99. }
  100. }
  101. void StartGame()
  102. {
  103. // LoadMetadataForAOTAssemblies();
  104. /*
  105. #if !UNITY_EDITOR
  106. _hotUpdateAss = Assembly.Load(ReadBytesFromStreamingAssets("HotUpdate.dll.bytes"));
  107. #else
  108. _hotUpdateAss = System.AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == "HotUpdate");
  109. #endif
  110. */
  111. _hotUpdateAss = Assembly.Load(LoadDll.ReadBytesFromStreamingAssets("HotUpdate.dll.bytes"));
  112. // Type entryType = _hotUpdateAss.GetType("Entry");
  113. // entryType.GetMethod("Start").Invoke(null, null);
  114. Run_InstantiateComponentByAsset();
  115. }
  116. private static void Run_InstantiateComponentByAsset()
  117. {
  118. // 通过实例化assetbundle中的资源,还原资源上的热更新脚本
  119. AssetBundle ab = AssetBundle.LoadFromMemory(LoadDll.ReadBytesFromStreamingAssets("gongye"));
  120. GameObject cube = ab.LoadAsset<GameObject>("gongye");
  121. instance.StartCoroutine(load(cube));
  122. }
  123. static IEnumerator load(GameObject cube)
  124. {
  125. yield return new WaitForSeconds(1f);
  126. GameObject.Instantiate(cube);
  127. }
  128. }