ILRuntime(一)

ILRuntime(一)之前简单的写了个 ILRuntime 和 Unity 互相调用的文章 https blog csdn net wangjiangron article details 感觉有蛮多不好的地方 所以想重新搞一搞 弄个简单的 ILRuntime 和 Unity 的基本框架 一些基本的概念在上面的文章讲过了 这边就懒得再说了 前期工作依旧是导入 ILRuntime 的库到 Unity 和一个 Hotf

之前简单的写了个ILRuntime和Unity互相调用的文章:https://blog.csdn.net/wangjiangrong/article/details/,感觉有蛮多不好的地方,所以想重新搞一搞,弄个简单的ILRuntime和Unity的基本框架。

一些基本的概念在上面的文章讲过了,这边就懒得再说了,前期工作依旧是导入ILRuntime的库到Unity,和一个Hotfix工程。

有兴趣的同学可以看下这个工程,里面有比较完整的代码,也是后续讲到UI相关的文章里面的Demo工程。

 

补充:官方文档说导入 Mono.Cecil.20,Mono.Cecil.Pdb,ILRuntime三个文件夹到Unity工程,但是在新下载的目录中,根目录下只有ILRuntime和Mono.Cecil两个目录,经测试,我们导入这两个目录,然后删除ILRuntime/ILRuntime.csproj和Mono.Cecil子目录中出了文件夹外的其他文件,同时删除子文件夹内所有会导致Unity编译报错的AssemblyInfo.cs文件

ILRuntime(一)

 

Unity部分

我们先把ILRuntime部分的内容,例如绑定适配器,注册委托等分成多个工具类,方便管理和查看,同时暴露出ILRuntime.Runtime.Enviorment.AppDomain实例,供外部使用。

注册委托的类ILRuntimeDelegateHelp

using System; namespace Tool { public class ILRuntimeDelegateHelp { //跨域委托调用,注册委托的适配器 public static void RegisterDelegate(ILRuntime.Runtime.Enviorment.AppDomain appdomain) { //Button 点击事件的委托注册 appdomain.DelegateManager.RegisterDelegateConvertor 
  
    ((act) => { return new UnityEngine.Events.UnityAction(() => { ((Action)act)(); }); }); } } } 
  

绑定适配器的类ILRuntimeAdapterHelp

namespace Tool { public class ILRuntimeAdapterHelp { //跨域继承绑定适配器 public static void RegisterCrossBindingAdaptor(ILRuntime.Runtime.Enviorment.AppDomain appdomain) { //appdomain.RegisterCrossBindingAdaptor(new InterfaceIUIAdaptor()); } } }

读取hotfix.dll的类ILRuntimeHelp

using System; using System.Collections; using System.IO; using UnityEngine; using UnityEngine.Networking; namespace Tool { public class ILRuntimeHelp { public static ILRuntime.Runtime.Enviorment.AppDomain appdomain; static MemoryStream m_hotfixDllMemoryStream; static MemoryStream m_hotfixPdbMemoryStream; public static IEnumerator LoadILRuntime(Action LoadedFinish) { appdomain = new ILRuntime.Runtime.Enviorment.AppDomain(); //把官方文档的WWW用UnityWebRequest替代了 UnityWebRequest webRequest = UnityWebRequest.Get("file:///" + Application.streamingAssetsPath + "/Hotfix.dll"); yield return webRequest.SendWebRequest(); byte[] dll = null; if (webRequest.isNetworkError) { Debug.Log("Download Error:" + webRequest.error); } else { dll = webRequest.downloadHandler.data; } webRequest.Dispose(); webRequest = UnityWebRequest.Get("file:///" + Application.streamingAssetsPath + "/Hotfix.pdb"); yield return webRequest.SendWebRequest(); byte[] pdb = null; if (webRequest.isNetworkError) { Debug.Log("Download Error:" + webRequest.error); } else { pdb = webRequest.downloadHandler.data; } //用下面的会报错:ObjectDisposedException: Cannot access a closed Stream. / using (MemoryStream fs = new MemoryStream(dll)) { using (MemoryStream p = new MemoryStream(pdb)) { appdomain.LoadAssembly(fs, p, new Mono.Cecil.Pdb.PdbReaderProvider()); } } / m_hotfixDllMemoryStream = new MemoryStream(dll); m_hotfixPdbMemoryStream = new MemoryStream(pdb); appdomain.LoadAssembly(m_hotfixDllMemoryStream , m_hotfixPdbMemoryStream , new Mono.Cecil.Pdb.PdbReaderProvider()); webRequest.Dispose(); webRequest = null; ILRuntimeDelegateHelp.RegisterDelegate(appdomain); ILRuntimeAdapterHelp.RegisterCrossBindingAdaptor(appdomain); //用于ILRuntime Debug if (Application.isEditor) appdomain.DebugService.StartDebugService(56000); LoadedFinish?.Invoke(); } public static void Dispose() { m_hotfixDllMemoryStream?.Dispose(); m_hotfixPdbMemoryStream?.Dispose(); } } } 

ILRuntime的类搞好之后,我们需要一个启动类Launch,用来加载调用热更的内容,同时管理热更内容的生命周期。

using System; using Tool; using UnityEngine; public class Launch : MonoBehaviour { public static Action OnUpdate { get; set; } public static Action OnLateUpdate { get; set; } public static Action OnFixedUpdate { get; set; } public static Action OnApplicationQuitAction { get; set; } private void Start() { StartCoroutine(ILRuntimeHelp.LoadILRuntime(OnILRuntimeInitialized)); } void OnILRuntimeInitialized() { ILRuntimeHelp.appdomain.Invoke("Hotfix.HotfixLaunch", "Start", null, null); } void Update() { OnUpdate?.Invoke(); } void LateUpdate() { OnLateUpdate?.Invoke(); } void FixedUpdate() { OnFixedUpdate?.Invoke(); } void OnApplicationQuit() { OnApplicationQuitAction?.Invoke(); ILRuntimeHelp.Dispose(); GC.Collect(); } }

 

Hotfix部分

需要热更的部分我们都需要放在Hotfix工程中,打成dll导入到Unity。我们需要一个主类提供一个接口给Unity调用,类似Main函数,然后在该类中去维护Hotfix部分的生命周期。例如

namespace Hotfix.Manager { public interface IManager { void Init(); void Start(); void Update(); void LateUpdate(); void FixedUpdate(); void OnApplicationQuit(); } }

一般一个项目会有多个功能模块,例如UI,对象池,网络等等,这些我们可以都用一个个的管理类来处理,我们先写一个基类

namespace Hotfix.Manager { public class ManagerBase 
  
    : IManager where T : IManager, new() { protected static T mInstance; public static T Instance { get { if (mInstance == null) { mInstance = new T(); } return mInstance; } } protected ManagerBase() { } public virtual void Init() { } public virtual void Start() { } public virtual void Update() { } public virtual void LateUpdate() { } public virtual void FixedUpdate() { } public virtual void OnApplicationQuit() { } } } 
  

然后需要的模块继承这个基类,例如

using UnityEngine; namespace Hotfix.Manager { class TimeManager : ManagerBase 
  
    { public override void Start() { base.Start(); Debug.Log("TimeManager start"); } } } 
  
using UnityEngine; namespace Hotfix.Manager { class UIManager : ManagerBase 
  
    { public override void Start() { base.Start(); Debug.Log("UIManager start"); } } } 
  

接着我们就需要一个主类,去由unity调用,然后启动我们的这些管理类。

using Hotfix.Manager; using System; using System.Collections.Generic; using System.Linq; using Tool; using UnityEngine; namespace Hotfix { class HotfixLaunch { static List 
  
    managerList = new List 
   
     (); public static void Start() { Debug.Log("HotfixLaunch Start"); //获取Hotfix.dll内部定义的类 List 
    
      allTypes = new List 
     
       (); var values = ILRuntimeHelp.appdomain.LoadedTypes.Values.ToList(); foreach (var v in values) { allTypes.Add(v.ReflectionType); } //去重 allTypes = allTypes.Distinct().ToList(); //获取hotfix的管理类,并启动 foreach (var t in allTypes) { try { if (t != null && t.BaseType != null && t.BaseType.FullName != null) { if (t.BaseType.FullName.Contains(".ManagerBase`")) { Debug.Log("加载管理器-" + t); var manager = t.BaseType.GetProperty("Instance").GetValue(null, null) as IManager; manager.Init(); managerList.Add(manager); continue; } } } catch (Exception e) { Debug.LogError(e.Message); } } //绑定生命周期方法 Launch.OnUpdate = Update; Launch.OnLateUpdate = LateUpdate; Launch.OnFixedUpdate = FixedUpdate; Launch.OnApplicationQuitAction = ApplicationQuit; foreach (var manager in managerList) manager.Start(); } static void Update() { foreach(var manager in managerList) manager.Update(); } static void LateUpdate() { foreach (var manager in managerList) manager.LateUpdate(); } static void FixedUpdate() { foreach (var manager in managerList) manager.FixedUpdate(); } static void ApplicationQuit() { Debug.Log("hotfix ApplicationQuit"); } } } 
      
     
    
  

 

最后导出dll和pdb文件到streamassets目录,将组件Launch挂载到场景中运行即可。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/205994.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午4:43
下一篇 2026年3月19日 下午4:43


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号