[专栏精选]Unity热更新之ILRuntime

本文节选自洪流学堂公众号技术专栏《大话Unity2019》,未经允许不可转载。

洪流学堂公众号回复专栏,查看更多专栏文章。


洪流学堂,让你快人几步!你好,我是你的技术探路者郑洪智,你可以叫我大智(vx: zhz11235)。

logo.png

小新:“热更新真的是打开了一片天啊,现在我越发感觉热更新能做的事情太多了。之前做了一个项目,每次打包都好花费半小时,如果有热更新,只需要替换一下dll就行了。”
大智:“没错,热更新可以大幅提高迭代效率,更能提高用户体验。”
小新:“那之前还提到了几个能兼容全平台的方案,我们也来学一学吧?”
大智:“那你可需要做好心理准备了,能兼容全平台的方案在学习曲线上都比较陡峭,不像前两天通过dll实现热更新时那么简单。”
小新:“那怕啥,这么多风风雨雨都走过来了,嘿嘿”
大智:“兼容全平台的热更新方案主要有两类C#类和lua类,lua还需要额外掌握lua语言。我们今天继续学习和C#联系更紧密的一种热更新方案,那就是ILRuntime。”

ILRuntime

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

ILRuntime的下载地址是:
ILRuntime源码
ILRuntime Unity Demo

ILRuntime的优势

同市面上的其他热更方案相比,ILRuntime主要有以下优点:

  • 无缝访问C#工程的现成代码,无需额外抽象脚本API
  • 直接使用VS2015进行开发,ILRuntime的解译引擎支持.Net 4.6编译的DLL
  • 执行效率是L#的10-20倍
  • 选择性的CLR绑定使跨域调用更快速,绑定后跨域调用的性能能达到slua的2倍左右(从脚本调用GameObject之类的接口)
  • 支持跨域继承
  • 完整的泛型支持
  • 拥有Visual Studio的调试插件,可以实现真机源码级调试。支持Visual Studio 2015 Update3 以及Visual Studio 2017

估计现在上面的有些优点你还不太明白,你只需要知道ILRuntime的优点很多就是啦,等后面我们学习了其他的热更新方案你可以亲自回来比较一下。

从0开始

学习一个新东西,我们首先需要看的就是文档和示例源码。

首先我们将Unity Demo的源码下载下来:ILRuntime Unity Demo

Unity工程

下载完后使用Unity打开,会有很多很多的报错,不用担心,你会看到错误的原因都是一样的,我们根据报错的提示进行修复。

Assets\Scripts\Examples\11_ValueTypeBinding\QuaternionBinder.cs(12,21): error CS0227: Unsafe code may only appear if compiling with /unsafe. Enable "Allow 'unsafe' code" in Player Settings to fix this error.

最后一句,在Player Settings里面勾选Allow 'unsafe' code 可以修复这个错误。

如图勾选

这一步做完后,工程中就只剩下warning了,我们先忽略这些warning。

dll工程

dll工程打开前一定要先打开一次Unity目录,用来生成dll文件,否则会有很多报错。
如果UnityEngine.dll找不到,可以手动设置。在Unity2018.3中,需要引入UnityEngine.CoreModule.dll,我的路径在这,方便你去找:C:\Program Files\Unity\Hub\Editor\2018.3.8f1\Editor\Data\Managed\UnityEngine\

如果还有报错,需要把Hotfix_Project的属性改成4.x,不超过4.6,因为目前IL官方声明支持到4.6。

Unity目录结构

我们先看一下示例工程的目录结构:


  • _Scenes:示例场景
  • ILRuntime、LitJson、Mono.Cecil.20、Mono.Cecil.Pdb:这些都是ILRuntime库的相关文件夹
  • Scripts:这个Demo相关的代码
  • StreamingAssets:Unity的特殊目录,动态加载
  • gmcs、link、smcs:ILRuntime的一些配置文件(Unity新版本中将gmcs和smcs合并为csc.rsp文件,用于配置一些预编译命令。先前的Allow 'unsafe' code错误也可以通过将smcs.rsp文件重命名为csc.rsp文件解决。)

1. HelloWorld

我们先来看下_Scenes/Examples/01_HelloWorld。

这里面主要的逻辑在一个代码文件中,和我们之前使用dll进行热更新时有些类似,我们来仔细分析一下。

using UnityEngine;
using System.Collections;
using System.IO;
using ILRuntime.Runtime.Enviorment;

public class HelloWorld : MonoBehaviour
{
    //AppDomain是ILRuntime的入口,最好是在一个单例类中保存,整个游戏全局就一个,这里为了示例方便,每个例子里面都单独做了一个
    //大家在正式项目中请全局只创建一个AppDomain
    AppDomain appdomain;

    void Start()
    {
        StartCoroutine(LoadHotFixAssembly());
    }

    IEnumerator LoadHotFixAssembly()
    {
        //首先实例化ILRuntime的AppDomain,AppDomain是一个应用程序域,每个AppDomain都是一个独立的沙盒
        appdomain = new AppDomain();
        //正常项目中应该是自行从其他地方下载dll,或者打包在AssetBundle中读取,平时开发以及为了演示方便直接从StreammingAssets中读取,
        //正式发布的时候需要大家自行从其他地方读取dll

        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        //这个DLL文件是直接编译HotFix_Project.sln生成的,已经在项目中设置好输出目录为StreamingAssets,在VS里直接编译即可生成到对应目录,无需手动拷贝
#if UNITY_ANDROID
        WWW www = new WWW(Application.streamingAssetsPath + "/HotFix_Project.dll");
#else
        WWW www = new WWW("file:///" + Application.streamingAssetsPath + "/HotFix_Project.dll");
#endif
        while (!www.isDone)
            yield return null;
        if (!string.IsNullOrEmpty(www.error))
            UnityEngine.Debug.LogError(www.error);
        byte[] dll = www.bytes;
        www.Dispose();

        //PDB文件是调试数据库,如需要在日志中显示报错的行号,则必须提供PDB文件,不过由于会额外耗用内存,正式发布时请将PDB去掉,下面LoadAssembly的时候pdb传null即可
#if UNITY_ANDROID
        www = new WWW(Application.streamingAssetsPath + "/HotFix_Project.pdb");
#else
        www = new WWW("file:///" + Application.streamingAssetsPath + "/HotFix_Project.pdb");
#endif
        while (!www.isDone)
            yield return null;
        if (!string.IsNullOrEmpty(www.error))
            UnityEngine.Debug.LogError(www.error);
        byte[] pdb = www.bytes;
        using (MemoryStream fs = new MemoryStream(dll))
        {
            using (MemoryStream p = new MemoryStream(pdb))
            {
                appdomain.LoadAssembly(fs, p, new Mono.Cecil.Pdb.PdbReaderProvider());
            }
        }

        InitializeILRuntime();
        OnHotFixLoaded();
    }

    void InitializeILRuntime()
    {
        //这里做一些ILRuntime的注册,HelloWorld示例暂时没有需要注册的
    }

    void OnHotFixLoaded()
    {
        //HelloWorld,第一次方法调用
        appdomain.Invoke("HotFix_Project.InstanceClass", "StaticFunTest", null, null);

    }

    void Update()
    {

    }
}

看完上面的代码你发现了什么?
和我们前两天学习的使用dll热更新的代码神相似,对不对?

总结

大智:“ILRuntime就是实现了一个运行时,绕过了iOS的限制。这样我们在使用的时候,你会发现和我们前两天学习的dll热更新基本是一致的。”

今日思考题

大智:“将前两天学习的内容,使用ILRuntime实现看看,会不会遇到什么问题?”
小新:“好嘞!”
大智:“收获别忘了分享出来!也别忘了分享给你学Unity的朋友,也许能够帮到他。”


洪流学堂公众号回复专栏,查看更多专栏文章。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容

  • 本文节选自洪流学堂公众号技术专栏《大话Unity2018》,未经允许不可转载。 洪流学堂公众号回复专栏,查看更多专...
    洪智阅读 7,069评论 2 11
  • 幸福满满的 一座山,或许要爬上千百遍才能慢慢去感受它,品味它,感谢它。东山就是这样! ...
    东原郡人阅读 186评论 0 1
  • 执行结果:
    龙马君阅读 180评论 0 1
  • 每个人都会有自己的梦想,也都有为了梦想激情饱满的时候,而这也正是我焦虑的开始... 疲惫的眼睛 吃午饭...
    OrdinaryW阅读 836评论 4 9
  • 这是一句很简单的话,但是我却没有做到。与之相反,我每天都会关注事情不好的一面。 比如觉得兼职很累不想干,自己买东西...
    爱所有的一切阅读 862评论 0 0