转载请标明出处:http://www.cnblogs.com/zblade/
对于游戏中的热更,目前主流的解决方案,分为Lua(ulua/slua/xlua/tolua)系和ILRuntime代表的c#系。今天就来探究一下ILRuntime是如何实现热更的流程的,新手入门,个中有错误理解,欢迎指正。
ILRuntime的原理
首先说一下lua的热更新基本过程,unity提供了AssetBundle的资源打包方式,这样可以通过资源的对比来更新最新的资源。而lua文件不需要编译,可以被打包进游戏的资源中,在游戏启动的过程中加载对应的脚本资源,今儿解释执行转换为字节码,在lua的虚拟机中执行,这种天然的设计,可以规避静态语言需要编译的环节。
C#代码在编写后,是需要执行编译的,才能起效,这样如果在手机端,没有对应的编译环境,那么对应的c#代码就无法实现热更。ILRuntime实现的基础,也是基于AssetBundle的资源热更新方式,将需要热更新的c#代码打包成DLL,放在工程的StreamingAssets下,在每次完成资源打包后,对应的DLL会被作为资源热更新出去。这样就规避了编译相关的环节,实现了热更。
文字讲述较为枯燥,看看示例代码是如何执行这个流程的:
1、ILRuntime的相关资料链接
可以在github上查找: ILRuntime
对应的unity3d的工程的例子:ILRuntime U3D例子
 
2、探究ILRuntime的例子
整个例子分为两个部分:
分别是热更新的工程和U3D主工程,那么先看看U3D工程:
较为重要的是两个部分,一个是ILRuntime需要用到的几个环境,重点是Mono.Ceil.20, Mono.Ceil.Pdb,ILRuntime三个文件夹,ILRuntime后续的版本将LitJson也加入进来了。
另一个关键点就是讲HotFix_Project.dll作为资源加入到StreamingAssets文件夹下,这样就可以被ab打包作为资源热更新出去。
接下来我们打开HotFix_Project:
 
得到的工程为:
 

重点分析一下引用,可以看到,该工程是引用了UnityEngine/UnityEngine.UI/Assembly-CSharp等几个U3D游戏主工程中的dll的,这样,可以在工程中直接调用对应的u3d相关的dll下的类和方法,示例代码:

 

只要using UnityEngine申明后,下面的代码就可以继承MonoBehaviour类,自然可以调用其中的相关类和方法。那么到这一步,就可以理解,在HotFix_Project中,我们是可以调用U3D游戏主工程的类和方法的,只要添加其相关的dll到工程的引用中。这样我们就完成了HotFix对U3D游戏主工程的调用的一条线路。

3、U3D游戏主工程调用HotFix_Project中的类型和相关方法
现在的调用都是交互式的,在完成了hotfix对u3d的调用后,我们接下来看看u3d是如何调用hotfix中的类和方法的。
取我们最常见和关注的反射作为一个示例,这样可以了解整个调用过程。
首先,需要加载hotfix的dll,来看看相关的代码:
 

整个竖屏截出来的图比较大,跟随箭头来看看流程:
1) 首先MonoBehaviour下的Start执行一个协程;
2) 实例化唯一的appdomain;
3) 加载hotfix的dll和pdb,可以看到,如果我们热更新相关的dll和pdb,是需要在这一步之前执行的,其实可以放在Awake中执行,当然这儿没有热更,我们就直接执行dll和pdb的加载;
4) 在完成dll和pdb的加载后,执行assembly的加载,这样我们可以获取到hotfix中的相关类和方法,属性等相关信息,相关可以查看源码即可了解。
5) 测试如何调用反射:
        Debug.Log("热更DLL中的类型我们均需要通过AppDomain取得");
var it = appdomain.LoadedTypes["HotFix_Project.InstanceClass"];
Debug.Log("LoadedTypes返回的是IType类型,但是我们需要获得对应的System.Type才能继续使用反射接口");
var type = it.ReflectionType;
Debug.Log("取得Type之后就可以按照我们熟悉的方式来反射调用了");
var ctor = type.GetConstructor(new System.Type[]);
var obj = ctor.Invoke(null);
Debug.Log("打印一下结果");
Debug.Log(obj);
Debug.Log("我们试一下用反射给字段赋值");
var fi = type.GetField("id", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
fi.SetValue(obj, );
Debug.Log("我们用反射调用属性检查刚刚的赋值");
var pi = type.GetProperty("ID");
Debug.Log("ID = " + pi.GetValue(obj, null));
让我们看看整个流程:
基于appdomain来获取类,然后获取type,对应的invoke, 也可以利用反射来修改对应的field的值。
 
总结:到这儿,我们就基本理清楚了基于ILRuntime如何实现hotfix和u3d主工程之间的相互调用,可以讲这样一套热更新方式嵌套到游戏的框架中,实现不用lua来实现热更。当然ILRuntime要转换到IL2CPP,还是有很多地方需要注意的,详情可以参考github上的相关手册。
 
 
 
 

对C#热更新方案ILRuntime的探究的更多相关文章

  1. unity 热更新方案ILRuntime

    https://github.com/meta-42/ILRuntime 教程 https://ourpalm.github.io/ILRuntime/public/v1/guide/index.ht ...

  2. Unity实现c#热更新方案探究(三)

    转载请标明出处:http://www.cnblogs.com/zblade/ 前面两篇文章从头到尾讲解了C#热更新的一些方案,从程序域来加载和卸载DLL,到使用ILRuntime来实现安卓和IOS平台 ...

  3. Unity代码热更新方案 JSBinding + SharpKit 首页

    目前Unity的代码更新方案有很多,主要以lua为主. JSBinding + SharpKit 是一种新的技术,他做了两件事情: JSBinding将C#导出到 JavaScript (引擎是 Mo ...

  4. 【腾讯Bugly干货分享】手游热更新方案xLua开源:Unity3D下Lua编程解决方案

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:http://mp.weixin.qq.com/s/2bY7A6ihK9IMcA0bOFyB-Q 导语 xL ...

  5. Unity3D 热更新方案(集合各位专家的汇总)

    http://blog.csdn.net/guofeng526/article/details/52662994 热更新”这个词,在Unity3D的应用下,是有些语义错误的,但是作为大家都熟知的一项技 ...

  6. Unity3D 热更新方案总结

    如何评价腾讯在Unity下的xLua(开源)热更方案? Unity 游戏用XLua的HotFix实现热更原理揭秘 腾讯开源手游热更新方案,Unity3D下的Lua编程 [Unity]基于IL代码注入的 ...

  7. 移动端热更新方案(iOS+Android)

    PPT资源包含iOS+Android 各种方案分析:https://github.com/qiyer/Share/blob/master/%E7%83%AD%E6%9B%B4%E6%96%B0%E5% ...

  8. iOS 热更新方案 - lance的专栏 - 博客频道 - CSDN.NET

    iOS 热更新方案 - lance的专栏 - 博客频道 - CSDN.NET Weex

  9. 腾讯开源手游热更新方案,Unity3D下的Lua编程

    原文:http://www.sohu.com/a/123334175_355140 作者|车雄生 编辑|木环 腾讯最近在开源方面的动作不断:先是微信跨平台基础组件Mars宣布开源,腾讯手游又于近期开源 ...

随机推荐

  1. cas 单点登录(SSO)实验之二: cas-client

    cas 单点登录(SSO)实验之二: cas-client 参考文章: http://my.oschina.net/indestiny/blog/200768#comments http://wenk ...

  2. C++类型转化:static_cast,reinterpret_cast,dynamic_cast,const_cast

    类型转换名称和语法 C风格的强制类型转换(Type Cast)很简单,不管什么类型的转换统统是: TYPE b = (TYPE)a C++风格的类型转换提供了4种类型转换操作符来应对不同场合的应用. ...

  3. 关于iOS常用的26中公共方法,可copy的代码

    1. 获取磁盘总空间大小 //磁盘总空间 + (CGFloat)diskOfAllSizeMBytes{ CGFloat size = 0.0; NSError *error; NSDictionar ...

  4. MT6575 充电流程

    1,目前充电主要包括Power Off Charging(关机充电) .IPO Charging(休眠充电)和 OS Charging(开机充电) 三个部分 2,Power Off Charging ...

  5. Learning ROS forRobotics Programming Second Edition学习笔记(八)indigo rviz gazebo

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS forRobotics Pro ...

  6. EBS form 之间跳转实现(form 关闭)

    实现 form CUXOMWB 使用 app_navigate.execute 打开 form CUXOEXPRAVA :然后 FROM CUXOEXPRAVA 上点击按钮 跳回from CUXOMW ...

  7. Android TV listView焦点平滑移动

    先上TV上效果图 Mark下思路: package com.test.ui; import java.lang.reflect.Method; import android.annotation.Su ...

  8. Android的Context Manager(服务管理器)源码剖析-android学习之旅(99)

    Context Manager介绍 Context Manager对应的进程是servicemanager进程,它先于Service Server和服务客户端运行,进入接收IPC数据的待机状态,处理来 ...

  9. 使用Puppeteer抓取受限网站

    不要相信前端是安全的,今天简单验证一下,但是希望大家支持正版,支持原作者,毕竟写书不易. 安装Puppteer npm install --save puppeteer 选择目标网站 我们这里选择胡子 ...

  10. 《深入理解java虚拟机》读书笔记1--java内存区域

    Java内存管理 本文主要介绍Java虚拟机运行时的内存区域是如何划分的.Java对象的创建过程.Java对象的内存布局.Java对象的访问定位 一:运行时区域划分 主要可以分为以下 几个: 程序计数 ...