之前简单的写了个ILRuntime和Unity互相调用的文章:https://blog.csdn.net/wangjiangrong/article/details/90294366,感觉有蛮多不好的地方,所以想重新搞一搞,弄个简单的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文件

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<UnityEngine.Events.UnityAction>((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 Debugif (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<T> : 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<TimeManager>{public override void Start(){base.Start();Debug.Log("TimeManager start");}}
}
using UnityEngine;namespace Hotfix.Manager
{class UIManager : ManagerBase<UIManager>{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<IManager> managerList = new List<IManager>();public static void Start(){Debug.Log("HotfixLaunch Start");//获取Hotfix.dll内部定义的类List<Type> allTypes = new List<Type>();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挂载到场景中运行即可。

ILRuntime(一)相关推荐

  1. Java和U3D比较,Unity热更方案 ILRuntime 和 toLua的比较

    前言 目前市面上流行的热更方案就是lua系列和ILRuntime,选取哪一种需要根据自己的项目进行比对. 无论是ILRuntime还是toLua都是市面上有在用到的热更方案.直观上来讲,都可以通过把代 ...

  2. unity热更新新方案,ILRuntime

    ILRuntime 是一个独立的.跨平台的 .NET Runtime,可用于在 Unity 中实现热更功能.使用 ILRuntime,您可以在游戏运行时加载和执行 C# 脚本,而不需要重新编译整个项目 ...

  3. Unity ILRuntime Debugger使用及常见问题

    目录 前言 1.安装 2.使用 3.常见问题 前言 ILRuntime支持在VS中断点调试,下面说一下ILRuntime Debugger的使用及常见问题. 1.安装 需要下载对应版本的ILRunti ...

  4. ILRuntime学习(之一)

    最近在学习ET框架,然后被群友告知,要先学ILRuntime.行吧,谁让咱是小白呢..... ILRuntime的学习资料我是参考的github上的教程https://ourpalm.github.i ...

  5. ILRuntime学习(之四)

    第5个例子讲解是重定向,原理按照官网的说法是:当IL解译器发现需要调用某个指定CLR方法时,将实际调用重定向到另外一个方法进行挟持,再在这个方法中对ILRuntime的反射的用法进行处理.例如new方 ...

  6. ILRuntime热更的小技巧

    文章目录 前因 后果 新的发现 前因 因为ILRuntime热更项目直接打包出来的DLL不能放置到AssetBundle里面打包 所以我看网上的代码都是读取DLL的bytes然后放置到一个text文件 ...

  7. ILRuntime学习——从零开始

    1, ILRuntime项目为基于C#的平台(例如Unity)提供了一个纯C#实现,快速,方便且可靠的IL运行时,使得能够在不支持JIT的硬件环境(如iOS)能够实现代码的热更新 2,无缝访问C#工程 ...

  8. Unity ILRuntime的基本实现流程(0基础)

    Windows-->package Manager,找到ILRuntime 如果找不到,配置一下根目录的manifest.json,文件头部增加 ================ {" ...

  9. ILRuntime篇:介绍并下载运行官方案例

    学习环境 Rider 2018.4 .Net Framework 4.7.2 Unity 2018.3 ILRuntime地址:https://github.com/Ourpalm/ILRuntime ...

  10. ILRuntime篇:前言

    前言: 2019.3.12更:我发现官网的UnityDemo注释十分完善,已经不需要再做教程了,如果还是看不懂,那边是C#功底不够扎实,所以本分类的文章主要是记录使用心得以及一些坑(如果有的话,哈哈) ...

最新文章

  1. C/C++存储区划分
  2. 太牛了,原来古人是这样铸造钱币的。。。
  3. uva 10003——Cutting Sticks
  4. REDIS 字典数据结构
  5. Unity3D基础13:给物品添加力
  6. 不到 20 人的互联网公司该去吗?
  7. vue2.0网易云音乐播放器 (实时更新)
  8. 局域网打印机共享怎么设置_局域网共享精灵 局域网内便节共享文件和打印机...
  9. UEFI——PCD研究
  10. 虚拟服务器会计科目,云服务器入什么会计科目
  11. 华为路ws5200设置虚拟服务器,华为WS5200无线路由器怎么设置?
  12. 机器学习之R语言caret包trainControl函数(控制调参)
  13. Zend Studio 12.5注册码破解
  14. java设计建议植物大战僵尸_基于Java的游戏设计之植物大战僵尸
  15. 进阶篇——数据库的索引
  16. mysql牵引例子_登录mysql数据库,创建名称为demo的数据,简述步骤。
  17. Android实战开发-Kotlin教程(布局篇 3.1)
  18. P2P知识(1)--P2P技术与信息安全
  19. 一、数组操作的基本函数
  20. 计算机系统结构的分类方法,计算机系统的分类

热门文章

  1. JQuery.validationEngine表单验证插件
  2. validationEngine
  3. 查看 Python 已安装模块的方法
  4. NKOI 3711 摆花
  5. 苹果正在为未来的Mac打造自己的处理器
  6. 使用MATLAB绘制二元函数图像
  7. 1.1、高考状元入北大
  8. lxr+glimpse安装
  9. Java实现代码计时功能(Spring计时工具类--StopWatch学习总结)
  10. 进入古诗文网站个人中心,绕过登录