在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
《Lua热更新》##《Lua热更新》发布说明: ++++“Lua热更新”开始了,立钻哥哥终于开始此部分的探索了。 ++++作为游戏发布迭代的重要技术:Lua热更新在网络游戏迭代更新中非常重要,特别是对于AppStore这样的平台,我们只需要定期更新主App,原则上可以随时灵活更新我们的以Lua热更新框架为基础的代码。 ++++当然,作为一项新引入的技术,我们通常是以【快速入门】=>【基础夯实】=>【中级进阶】=>【高级实战】=>【立钻哥哥带您学Lua热更新】等几个阶段进行探索。 ##《Lua热更新》目录: #第一篇:Lua快速入门篇 #第二篇:Lua基础夯实篇 #第三篇:Lua中级进阶篇 #第四篇:Lua高级实战篇 #第五篇:立钻哥哥带您学Lua热更新 #第一篇:Lua快速入门篇#第一篇:Lua快速入门篇 ++++第一章:Lua基础概述 ++++第二章:xLua教程 ++++第三章:Lua基础拓展 ++++第四章:立钻哥哥带您学Lua热更新 ##第一章:Lua基础概述++第一章:Lua基础概述 ++++1.1、Lua热更新框架 ++++1.2、toLua#热更新框架 ++++1.3、xLua热更新框架 ++++1.4、立钻哥哥带您学Lua基础 ###1.1、Lua热更新框架++1.1、Lua热更新框架 ++++toLua:https://github.com/topameng/tolua ++++uLua: http://ulua.org/index.html ++++xLua: https://github.com/Tencent/xLua ++++C#在开发效率和运行效率平衡得很好,语言特性也比较全,是很优秀的一门语言。 ++++lua被称为游戏脚本之王,在游戏领域应用比较广泛,它设计之初就考虑到嵌入式领域,比如相对它提供的特性来说,它体积非常小,启动占资源也不多,性能是脚本里的佼佼者。 ++++lua相对于C#而言,首先是它支持解析执行,进而支持热更新。(免编译对开发效率提升也很大,特别是较大的项目。)(从运行效率上说C#比最快的lua方案也要快50倍左右。) ++++IOS不能热更新,不是因为不能用反射,是因为【System.Reflection.Assembly.Load】、【System.Reflection.Emit】、【System.CodeDom.Compiler】等无法使用,Unity原生的代码逻辑,无论是以前的MonoAOT或者后来的il2cpp,都是编译成native code,iOS下是跑不了的,立钻哥哥:IOS下不能动态载入dll或者cs文件,已经编译进App的没有问题。 ++++立钻哥哥:以lua热更技术为基础的框架有:toLua、uLua、xLua、SLua、C#light等。(ulua+ngui)(tolua+gui)(xlua+ngui)(ulua作者已不再维护,转至tolua)(tolua的性能表现好) ++1.1.1、toLua ++++toLua(gitHub):https://github.com/topameng/tolua ++++toLua是一个工具,将Unity的C#代码包装之后导出给Lua,同时提供了一些访问Lua的接口,使得Unity和Lua可以相互调用。 ++++toLua#是Unity静态绑定Lua的一个解决方案,它通过C#提供的反射信息分析代码生成包装的类。(它是一个用来简化在C#中集成Lua的插件,可以自动生成用于在Lua中访问Unity的绑定代码,并把C#中的常量、变量、函数、属性、类以及枚举暴露给lua。) ++++toLua#底层库是使用toLua(C语言编写),那么就需要通过C#来调用原生代码。 ++++toLua#集成主要分两部分: --第一部分:运行时需要的代码,包括一些手写的和自动生成的绑定代码; --第二部分:编辑器相关代码,主要提供代码生成、编译lua文件等操作,具体就是Unity编辑器中提供的功能。
++++【ToLua/Assembly-CSharp】:References/、Source/、ToLua/ --【References/】: --【Source/】:Generate/、LuaConst.cs ----Generate/:这个文件里面是生成的绑定代码; ----LuaConst.cs:这个文件是一些lua路径等配置文件; --【ToLua/】:BaseType/、Core/、Examples/、Misc、Reflection、ReadMe.txt ----BaseType/:一些基础类型的绑定代码; ----Core/:提供的一些核心功能,包括封装的LuaFunction、LuaTable、LuaThread、LuaState、LuaEvent、调用tolua原生代码等; ----Examples/:示例代码; ----Misc/:杂项,包括LuaClient、LuaCoroutine(协程)、LuaLooper(用于tick)、LuaResLoader(用于加载Lua文件); ----Reflection/:反射相关; ++++【ToLua/Assembly-CSharp-Editor】:References/、Editor/、ToLua/ --【Editor/Custom/CustomSettings.cs】:自定义配置文件,用于定义哪些类作为静态类型、哪些类需要导出、哪些附加委托需要导出等。 --【ToLua/Editor】:Extend/、ToLuaExport.cs、ToLuaMenu.cs、ToLuaTree.cs ----Extend/:扩展一些类的方法; ----ToLuaExport.cs:真正生成Lua绑定的代码; ----ToLuaMenu.cs:Lua菜单上功能对应的代码; ----ToLuaTree.cs:辅助树结构; ++++Generate All流程:生成绑定代码主要放在ToLuaExport.cs里面: --【GenLuaDelegates()函数】:生成委托绑定的代码,它会从CustomSettings.customDelegateList里面取出所有自定义导出的委托列表,然后把CustomSettings.customTypeList里面的所有类型中的委托根据一定规则加入到list中,最后调用ToLuaExport.GenDelegates()方法来生成委托绑定的代码,生成的代码在DelegateFactory.cs文件中。(立钻哥哥:该函数的详细实现可查看ToLuaExport.cs中的函数实现。) --【GenerateClassWraps()函数】:遍历所有需要导出的类,然后调用ToLuaExport.Generate()方法来生成类的绑定代码。 ++1.1.2、uLua ++++uLua.org: http://ulua.org/index.html ++++uLua:基于tolua#的Lua热更新UGUI/NGUI框架。(uLua已停止维护,由toLua#代替。) ++++uLua的原理:给GameObject添加上一个C#脚本组件作为中间层,在中间层上绑定上一个Lua脚本,将Unity的所有回调接口通过中间层传递到Lua。(Lua脚本也可以通过中间层操作GameObject。) ++++uLua要使用最新版本,早期的uLua是使用反射机制,脚本的运行效率比较糟糕,新的uLua集成了cstolua,预先生成一批代码把Unity的类和函数导出给lua,然后lua再调用,这样无论是效率还是GC的角度说都是比较完美的。 ++1.1.3、xLua ++++xLua官方: https://github.com/Tencent/xLua ++++xLua是Unity3D下Lua编程解决方案,腾讯已将xLua开源到GitHub。 ++++xLua是2015年3月完成第一个版本;2016年12月末,xLua实现新的突破:全平台支持用Lua修复C#代码bug。 ++++xLua为Unity、.Net、Mono等C#环境增加Lua脚本编程的能力,借助xLua,这些Lua代码可以方便和C#相互调用。(xLua在功能、性能、易用性都有不少突破。) ++++xLua的突破:1、可以运行时把C#实现(方法,操作符,属性,事件等等)替换成lua实现;2、出色的GC优化,自定义struct,枚举在Lua和C#间传递无C# gc alloc;3、编辑器下无需生成代码,开发更轻量。 ++++xLua热补丁技术支持在运行时把一个C#实现(函数,操作符,属性,事件,或者整个类)替换成Lua实现,意味着我们可以:1、平时用C#开发;2、运行也是C#,性能秒杀Lua;3、有bug的地方下发个Lua脚本fix了,下次整体更新时可以把Lua的实现换回正确的C#实现,更新时甚至可以做到不重启游戏; ++++xLua热修复框架工程结构参考:
++++【Resource/xLua/Main.lua】:xlua热修复入口。 ++++【Resource/xLua/Common/】:提供给lua代码使用的一些工具方法,提供lua逻辑代码到C#调用的一层封装。 ++++【Scripts/xLua/XLuaManager.cs】:xLua热修复环境,包括luaState管理,自定义loader。 ++++【Scripts/xLua/Util/】:为xLua的lua脚本提供的C#侧代码支持,被Resources/xLua/Common/所使用。 ++++【Scripts/HotfixTest】:需要热修复的C#脚本。 ++++【Resource/xLua/HotFix】:热修复脚本。 ###1.2、toLua#热更新框架++1.2、toLua#热更新框架 ++++toLua:https://github.com/topameng/tolua ++++toLua#是Unity静态绑定lua的一个解决方案,它通过C#提供的反射信息分析代码并生成包装的类。它是一个用来简化在C#中集成lua的插件,可以自动生成用于在lua中访问Unity的绑定代码,并把C#中的常量、变量、函数、属性、类以及枚举暴露给lua。 ++++【Unity C#】<==>【Tolua#】<==>【Tolua(c)】 ++++toLua特性: --自动生成绑定代码文件,非反射调用; --大量内建基础类型支持,如枚举,委托,事件,Type,数组,迭代器等; --支持多种协同形式; --支持所有unity内部类导出,支持委托类型导出; --支持导出自定义,跳过某个空的基类,修改导出名称等; --支持扩展函数自定义导出,比如DoTween; --支持值类型Nullable导出,包括Nullable<Vector3>等; --支持Lua中function转委托,可以区分需要不同委托的参数的重载函数; --支持C# LuaFunction对象转委托,简化调用方式。支持无GC的多参数调用形式; --支持重载函数自动排序,如:参数个数相同,object参数执行级最低,不会出现错误匹配情况; --支持导出函数重命名,可以分离导出某个重载函数(可以导出被折叠掉的函数); --支持使用编辑器类改写导出规则; --支持this数组访问,索引为int可以通过[]访问,其他可使用.get_Item或者.this.get()访问数组成员; --支持委托(事件)+-lua function。支持通过函数接口的Add和Remove委托操作; --支持静态反射操作,形式同C#; --支持peer表,可在lua端扩展导出的userdata; --支持自定义struct压入和读取,做到无GC,并且结构成员无类型限制; --支持preloading,可以通过require后绑定wrap文件; --支持int64,unit64; --大量的lua数学类型,如Quaternion, Vector3, Mathf等; --包含第三方lua扩展,包括luasocket, struct, lpeg, utf8, pb等库; --当lua出现异常,能够同时捕获C#端和lua端堆栈,便于调试; --print信息,在编辑器点击日志,能自动打开对应lua文件; --支持unity所有版本; --支持Lua hook C#代码实现,一定程度上支持利用Lua代码修改C#端代码的bug; ++++tolua#集成主要两部分:1、运行时需要的代码包括一些手写和自动生成的绑定代码,2、编辑器相关代码,主要提供代码生成、编译lua文件等操作,具体就是Unity编辑器中提供的功能。 ++1.2.1、【MenuItem(“Lua/Generate All”)】流程 ++++ToLuaMenu.cs/GenLuaAll():GenLuaDelegates()、GenerateClassWraps()、GenLuaBinder(): --【GenLuaDelegate()】:生成委托绑定代码,它会从CustomSettings.customDelegateList里面取出所有自定义导出的委托列表,然后把CustomSettings.customTypeList里面的所有类型中的委托根据一定规则加入到list中,最后调用ToLuaExport.GenDelegates()方法来生成委托绑定的代码,生成的代码在DelegateFactory.cs文件中。 --【GenerateClassWraps()】:遍历所有需要导出的类,然后调用ToLuaExport.Generate()方法来生成类的绑定代码。 --【GenLuaBinder()】:生成向lua注册C#类的绑定代码,这个代码存放在LuaBinder.cs文件中,这部分代码中不包含BaseType(Array、Enum、Object、String等等)的注册。 //立钻哥哥:GenLuaAll(tolua-master-\Assets\ToLua\Editor\ToLuaMenu.cs) using UnityEngine; using UnityEditor; using System;
[InitializeOnLoad] public static class ToLuaMenu{ [MenuItem(“Lua/Generate All”, false, 5)] static void GenLuaAll(){ if(EditorApplication.isCompiling){ EditorUtility.DisplayDialog(“立钻哥哥警告”, “请等待编辑器完成编译再执行此功能”, “确定”); return; }
beAutoGen = true; GenLuaDelegates(); AssetDatabase.Refresh(); GenerateClassWraps(); GenLuaBinder(); beAutoGen = false; }
[MenuItem(“Lua/Gen Lua Delegates”, false, 2)] static void GenLuaDelegates(){ if(!beAutoGen && EditorApplication.isCompiling){ EditorUtility.DisplayDialog(“立钻哥哥警告”, ”请等待编辑器完成编译再执行此功能”, “确定”); return; }
ToLuaExport.Clear(); List<DelegateType> list = new List<DelegateType>(); list.AddRange(CustomSettings.customDelegateList); HashSet<Type> set = GetCustomTypeDelegates();
foreach(Type t in set){ if(null == list.Find((p)=>{ return p.type == t; })){ list.Add(new DelegateType(t)); } }
ToLuaExport.GenDelegates(list.ToArray()); set.Clear(); ToLuaExport.Clear(); AssetDatabase.Refresh();
Debug.Log(“立钻哥哥:Create lua delegate over!”); }
[MenuItem(“Lua/Gen Lua Wrap Files”, false, 1)] public static void GenerateClassWraps(){ if(!bAutoGen && EditorApplication.isCompiling){ EditorUtility.DisplayDialog(“立钻哥哥警告”, “请等待编辑器完成编译再执行此功能”, “确定”); return; }
if(!File.Exists(CustomSettings.saveDir)){ Directory.CreateDirectory(CustomSettings.saveDir); }
allTypes.Clear(); BindType[] typeList = CustomSettings.customTypeList;
BindType[] list = GenBindTypes(typeList); ToLuaExport.allTypes.AddRange(baseType);
for(int i = 0; i < list.Length; i++){ ToLuaExport.allTypes.Add(list[i].type); }
for(int i = 0; i < list.Length; i++){ ToLuaExport.Clear(); ToLuaExport.className = list[i].name; ToLuaExport.type = list[i].type; ToLuaExport.isStaticClass = list[i].IsStatic; ToLuaExport.baseType = list[i].baseType; ToLuaExport.wrapClassName = list[i].wrapName; ToLuaExport.libClassName = list[i].libName; ToLuaExport.extendList = list[i].extendList; ToLuaExport.Generate(CustomSettings.saveDir); }
Debug.Log(“立钻哥哥:Generic lua binding files over!”); ToLuaExport.allTypes.Clear |
请发表评论