找回密码
 立即注册
查看: 306|回复: 0

XLua心得

[复制链接]
发表于 2021-8-14 22:49 | 显示全部楼层 |阅读模式
一. xlua简介
   xlua是由腾讯维护的一个开源项目,除了常规的Lua绑定之外,还有一个比较有特色的功能就是代码热补丁。非常适合前期没有规划使用Lua进行逻辑开发,后期又需要在iOS这种平台获得代码热更新能力的项目。
刚开始学习使用xlua,主要实现原理暂时还未进行深究,研究过后将会在之后的内容里补上。这里先祭上官方的一张图来简单描述一下:




传送门系列:


  官网:

https://github.com/Tencent/xLua

  配置文档:

https://github.com/Tencent/xLua/blob/master/Assets/XLua/Doc/hotfix.md

  官方FAQ:

https://github.com/Tencent/xLua/blob/master/Assets/XLua/Doc/faq.md

  代码生成引擎:

https://github.com/Tencent/xLua/blob/master/Assets/XLua/Doc/custom_generate.md

  Lua5.3官方手册:

https://www.lua.org/manual/5.3/manual.html


    关于xlua和lua的基础知识,在官网上和其他一些教程里都有详细的描述,我这边就不贴了,这次主要说一下我在学习使用xlua时遇到的  问题已经需要注意的一些地方,最后奉上自己使用Unity和xlua交互制作的一个小程序和一个xlua热更新的例子。好的,那我就先从热更新开始啦~


二.  xlua热更新



    第一,当然是将xlua添加到我们的工程里,在github上下载xlua之后,将 xlua-master/Assets下的内容拷贝到我们的工程里,因为之后制作热更新的时候需要使用tools文件夹下的XLuaHotfixInject.exe 文件,所以我这边直接将tools文件也整个拷贝到工程里,在真实的项目里大家根据需求有选择的拷贝就好。另外有一点需要注意的是,全拷贝tools文件夹下的内容到工程里的话,Unity会报出重复定义的错误:




此时,将tools里的 System.Core.dll 删除就可以了。
    第二,在BuildSettings里添加两个宏:
     HOTFIX_ENABLE:开启热更新特性,编辑器,各手机平台需要手动单独设置,如果是自动化打包,要注意在代码里用API设置的宏是不生效的,需要在编辑器里设置。
     INJECT_WITHOUT_TOOL:采用内嵌到编辑器的方式注入。添加了该宏之后,在菜单栏XLUA里才能够进行【Hotfix inject in Editor】的操作;在构建手机包的时候这个步骤会在构建时自动进行,编辑器模式下开发补丁需要手动执行Hotfix inject in Editor进行注入。
     定义INJECT_WITHOUT_TOOL宏后,热补丁特性依赖Cecil,添加HOTFIX_ENABLE宏之后,可能会报找不到Cecil。这时你需要到Unity安装目录下找到Mono.Cecil.dll,Mono.Cecil.Pdb.dll,Mono.Cecil.Mdb.dll,拷贝到项目里头。
    注意:如果你的Unity安装目录没有Mono.Cecil.Pdb.dll,Mono.Cecil.Mdb.dll(往往是一些老版本),那就只拷贝Mono.Cecil.dll(你从别的版本的Unity拷贝一套可能会导致编辑器不稳定),这时你需要定义HOTFIX_SYMBOLS_DISABLE,
    这会导致C#代码没法调试以及Log的栈源文件及行号错乱(所以赶紧升级Unity)。

    以上两个宏若是不开启,或者在没有成功进行Hotfix inject in Editor操作直接运行的话,系统会抛出 LuaException: xlua.access, no field __Hotfix0_hotfix


第三,对需要热更的代码部分添加[Hotfix]标签,这样xLua就知道这个类或者方法等可能会有热更新的需求。
  [C#]   纯文本查看复制代码
?

        01      

        02      

        03      

        04      

        05      

        06      

        07      

        08      

        09      

        10      

        11      

usingUnityEngine;
usingSystem.Collections;
usingXLua;

[Hotfix]
publicclassHotfixTest_easy{

publicvoidHotFixEasy()
{
Debug.Log("Unity调用");
}
}






    第四,Unity侧的调用:
  [C#]   纯文本查看复制代码
?

        01      

        02      

        03      

        04      

        05      

        06      

        07      

        08      

        09      

        10      

        11      

        12      

        13      

        14      

        15      

        16      

        17      

        18      

        19      

        20      

        21      

        22      

        23      

        24      

        25      

        26      

        27      

        28      

        29      

        30      

        31      

        32      

        33      

        34      

        35      

        36      

        37      

        38      

usingUnityEngine;
usingSystem.Collections;
usingXLua;

publicclassHotFixMono : MonoBehaviour {

XLua.LuaEnv m_kLuaEnv = null;

privateHotfixTest_easy fixEasy = null;
// Use this for initialization
privateboolisShow = false;
voidStart () {

//代码热更步骤
m_kLuaEnv = newLuaEnv();  //该变量最好保证全局就此一个

//1.查找指定路径下lua热更文件
TextAsset txt = Resources.Load("HotfixTest_easy.lua") asTextAsset;

//2.如果存在lua热更文件,则执行lua文件的执行,否则不执行(也就是说,到底是读取C#本地代码还是LUA热更代码是由我们自己控制,xlua框架并不提供识别机制,这只是我现在的个人理解,如果不正确,请一定要告知我!)
if(txt != null)
{
m_kLuaEnv.DoString(txt.text, "HotfixTest_easy.HotFixEasy");  //这个方式是替换指定的方法
}

fixEasy = newHotfixTest_easy();
}

// Update is called once per frame
voidUpdate()
{

if(!isShow)
{
isShow = true;
fixEasy.HotFixEasy();
}
}
}






    第五,Lua侧(蛮牛不能插入lua的代码,看起来很不方便啊):
HotfixTest_easy = {}

function HotfixTest_easy.HotFixEasy()
        print("xxxxxxx lua cast")
end;

xlua.private_accessible(CS.HotfixTest_easy)
xlua.hotfix(CS.HotfixTest_easy,'HotFixEasy',HotfixTest_easy.HotFixEasy)

几个重要的xlua API:
xlua.hotfix(class, [method_name], fix)
描述 : 注入lua补丁
class : C#类,两种表示方法,CS.Namespace.TypeName或者字符串方式"Namespace.TypeName",字符串格式和C#的Type.GetType要求一致,如果是内嵌类型(Nested Type)是非Public类型的话,只能用字符串方式表示"Namespace.TypeName+NestedTypeName";
method_name : 方法名,可选;
fix : 如果传了method_name,fix将会是一个function,否则通过table提供一组函数。table的组织按key是method_name,value是function的方式。

xlua.private_accessible(class)

描述 : 让一个类的私有字段,属性,方法等可用
class : 同xlua.hotfix的class参数

util.hotfix_ex(class, method_name, fix)
描述 : xlua.hotfix的增强版本,可以在fix函数里头执行原来的函数,缺点是fix的执行会略慢。
method_name : 方法名;
fix : 用来替换C#方法的lua function。

第六,执行xlua/Generate Code--->执行XLua/Hotfix Inject In Editor,其中,执行后者的时候,因为XLUA源代码里需要找到XLuaHotfixInject.exe(tools里)才能运行,需要收到修改代码里找到该文件的路径(反正为了运行我暂时先改了)

第七,运行。

运行结果:

当热更新目录(我这里为了方便暂时放在Resource文件夹下)里不存在指定的文件时,则执行C#定义的方法:







当存在指定的文件时,则进行热更新的操作:







以上仅仅用一个简单的例子给大家掩饰了使用xlua进行代码热更新的流程,还有很多xlua强大的功能没有涉及到,本文也是一个抛砖引玉,最主要的还是记录我自己学习过程,我没有弟子来记录我平时的言行语录,我就自己来!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-24 11:48 , Processed in 0.149779 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表