鸣谢:Burnner
一、不同平台热更新的比较Android 应用的热更新• 将执行代码预编译为assembly dll。
• 将代码作为TextAsset打包进Assetbundle。
• 运行时,使用Reflection机制实现代码的功能。
• 更新相应的Assetbundle即可实现热更新。
Android 与iOS 热更新的异同• 苹果官方禁止iOS下的程序热更新;JIT在ios下无效。
• 热更新方案:Unity+Lua插件
二、热更新的各种Lua 插件的对比3.1、uLua(asset store)• uLua插件原生版本,开山鼻祖
• 不会产生静态代码
• 反射机制,效率低下,速度慢,gc alloc频繁
• 已停止更新维护,不支持Unity5.x,淡出主流
3.2、XLua(腾讯2017年开源的手游热更新方案)• 开发只用C#;
• 运行也是C#,性能可以秒杀lua;
• 出问题了才用Lua来改掉C#出问题的部位,替换甚至做到不用重启游戏;
• 补丁需要预打入
• 开头加入几个il指令对性能的开销
开源项目地址
https://github.com/Tencent/xLua
3.2、uLua & cstoLua(合并后叫做toLua)• 开发平台成熟稳定,Bug修复迅速
• 开发者众多,资源丰富
• 静态方法,性能优
• 有成功商业产品案例(啪啪三国、超神战队、酷鱼吧捕鱼、绝地战警、这不是刀塔等)
• 都是基于原生版本的改进;未来,两者会合并成一个插件
开源项目地址:
https://github.com/topameng/tolua
3.3、sLua• 静态方法,性能优
• 核心代码简洁
• 资源较少,开发平台不够成熟稳定
• 无成功商业产品案例成功商业产品案例
• 基于原生版本的改进
开源项目地址:
https://github.com/pangweiwei/slua
3.4、C#Light(L#)• 淡出主流,想要了解的小伙伴点击这里:
https://github.com/lightszero/LSharp
3.5、 uniLua• c#实现的Lua虚拟机,非完整方案
• 淡出主流
三、使用Lua 插件进行 热更新的总体流程综合上面这些热更新插件的分析跟对比,比较可靠跟稳定的热更新方案一个是腾讯的xLua热更新框架。一个是uLua+cstoLua结合的toLua框架。接下来就对这两个框架进行具体的分析。 以上的参考: http://blog.csdn.net/guofeng526/article/details/52662994 http://www.cnblogs.com/muyuqianshan/p/6937096.html 四、Xlua热更新方案分析项目地址:https://github.com/Tencent/xLua 4.1 Unity热更新遭遇的问题目前Unity下的热更新方案有不少,这些方案都要求要热更新的地方一开始就得用脚本来实现,这带来一些问题:
1、接入成本高,有的项目已经用C#写完了,这时要接入需要把需要热更的地方用脚本重新实现;
2、即使一开始就接入了,也存在同时用两种语言开发难度较大的问题,有些项目只是想fix下bug而已,却被迫使用两种语言开发,明显代价有点大;
3、脚本性能不如C#;
4.2、xlua的更新方案思路(另类Unity热更新大法:代码注入式补丁热更新) 之前的unity热更新的方案都是在需要热更新的地方通过c#调用lua来实现热更新的。因而或多或少的会遭遇到4.1所说的三个问题。毕竟C#是一门编程语言,它运行之前需要进行编译,而这个编译的过程在移动平台无法完成,所以当我们游戏的逻辑更改,C#代码发生改变的时候,我们就需要重新在开发环境下编译,然后重新打包,然后让玩家去下载更新最新的版本。
好像在需要更新的地方也只能选择lua、js这样的脚本语言来实现动态加载更新了。看起来好像是最好的解决方案了。但是反观Unity之外有不少方案,比如ios下的jspatch,android下的tinker等,并没这约束。以jspatch为例,它支持把一个oc函数替换为js实现,平时开发可以只写oc,只有出现bug,才需要写个js去fix。而xlua就是这样的一个解决方案。
xLua热补丁技术支持在线把一个C#(方法,属性,事件等等)实现替换成Lua实现。这意味着你可以: 1、开发只用C#; 2、运行也是C#,性能可以秒杀lua; 3、出问题了才用Lua来改掉C#出问题的部位,替换甚至做到不用重启游戏; 用完即走,是小龙哥对一个好工具的定义,xLua这个特性也如此:没问题的时候你感觉不到它的存在,出了问题才需要它来救场。而你只需要在需要热修复的地方打上hotfix标签。 4.3两条指令的性能开销xLua会在C#编译成il后插入一个处理,该处理会从il层面为每个打了Hotfix标签的类型的函数开头加入几个il指令,如果用C#描述是这样的:
public int Add(int a, int b)
{
return a + b;
}
// 加了il指令:
static Func<object,int,="" int=""> hotfix_Add = null;
public int Add(int a, int b)
{
if (hotfix_Add !=null) return hotfix_Add(this, a, b);
return a + b;
}
如果lua中执行了hotfix调用,hotfix_Add会指向一个lua的适配函数。
性能开销:
如果不打补丁,就一个if判断,比注入前多执行两条很轻量级的指令(Ldsfld,Brfalse),我在window下测试,这两指令加起来仅相当于空函数调用开销的十分之一到五分之一。
内存开销:
每个函数会多一个静态delegate引用,注意是静态的,和对象实例个数无关。(Stateful方式会略不同,后面单独分析)。
安装包影响:
一般情况,就一个if和delegate调用。如果泛化函数以及参数含非public类型参数或返回值的函数会多一点:每一个输入参数,每个输出参数,对应一次函数调用,外加三次函数调用。
4.4热补丁支持的C#特性• 各种函数,包括私有/公有,静态/成员,操作符重载,泛化函数。
• 构造函数,析构函数,和普通函数不一样的是,构造函数和析构函数并不是用lua函数替换了,而是执行了lua函数后还会执行原来的逻辑。
• 属性,包括私有/公有,静态/成员,泛化的。
• 事件的add/remove。
• 泛化类型。
• 总而言之,目前已知唯一尚不支持的是类静态构造函数。
4.5 xLua的突破xLua在功能、性能、易用性都有不少突破,这几方面分别最具代表性的是:
• 可以运行时把C#实现(方法,操作符,属性,事件等等)替换成lua实现;
• 出色的GC优化,自定义struct,枚举在Lua和C#间传递无C# gcalloc;
• 编辑器下无需生成代码,开发更轻量;
参考:https://github.com/Tencent/xLua http://gad.qq.com/article/detail/7182056 https://www.zhihu.com/question/54344452
五 toLua热更新方案分析项目地址:https://github.com/topameng/tolua 5.1 toLua历史版本toLua的衍化版本:uLua(反射时代)->uLua+cstoLua(去反射时代) -> toLua(新一代引擎时代)。
最早的2004年ulua从国外引进到国内,可以说uLua使得国内的Unity热更新领域被揭开了序幕。toLua框架经过了120多个上线商业手机游戏的测试,已经趋于成熟。并且其中腾讯、盛大、巨人、完美、畅游等等众多著名大厂均已经推出基于ulua的名作。
相比于最早的ulua框架,toLua可谓是卷土重来,从高效率、稳定性、代码质量等方面都提升N倍,重写的引擎:代码简洁,逻辑清晰明了,是代码优雅+效率之神完美化身,从此tolua #将代替ulua走上Unity热更新舞台。
5.2 toLuatolua#是Unity静态绑定lua的一个解决方案,它通过C#提供的反射信息分析代码并生成包装的类。它是一个用来简化在C#中集成lua的插件,可以自动生成用于在lua中访问Unity的绑定代码,并把C#中的常量、变量、函数、属性、类以及枚举暴露给lua。它是从cstolua衍变而来。从它的名字可以看出,它是集成了原来的tolua代码通过二次封装写了一个C#与tolua(c)的一个中间层。
|