之前简单的写了个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文件

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
