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

xLua热更新(二)实现热更新

[复制链接]
发表于 2023-1-31 08:55 | 显示全部楼层 |阅读模式
一、环境配置

要实现热更新功能,我们首先需要开启热更新的宏。操作方法是在「File->Build Settings->Player Settings->Player->Other Settings->Scripting Define Symbols」选项中添加HOTFIX_ENABLE



开启后,在xLua的菜单中就出现了「Hotfix Inject In Editor」选项。



当我们在开发补丁版本需要进行热更新测试时,都需要点击一次上图中的「Generate Code」选项重新生成一次代码,然后再点击「Hotfix Inject In Editor」进行注入。
如果注入时出现了如下错误信息,我们需要将xLua源码中的「Tools」文件夹复制到我们工程的根目录下。



以上两步操作如果成功的话,在控制台都会有相应提示。环境配置完成后,可以运行xLua自带的热更新示例,测试一下是否能热更成功。



二、热更新原理

首先引用一段xLua作者的话,介绍一下xLua实现热更新的原理(原文出处)

热补丁的基本原理其实非常简单,了解后任何程序员都很容易分析出开销,比如对于这个类
  1. publicclassCalc{intAdd(int a,int b){return a + b
  2.    }}
复制代码
打了hotfix标签后,xLua会在il层面注入代码,注入之后这个类会类似这样:
  1. publicclassCalc{staticFunc<object,int,int,int> hotfix_Add =null;intAdd(int a,int b){if(hotfix_Add !=null)returnhotfix_Add(this, a, b);return a + b
  2.    }}
复制代码
如果lua中执行了hotfix调用,hotfix_Add会指向一个lua的适配函数。

也就是说,在给类加上[Hotfix]特性后,我们就可以在Lua中指定需要“替换”的方法。然后xLua就会将委托指向Lua中对应的函数。
明白了原理后,我们来尝试实现一个简单的案例
比如原本有一个C#脚本如下所示
  1. [Hotfix]publicclassHotfixExample:MonoBehaviour{privatefloat _timer =0f;[LuaCallCSharp]privatevoidUpdate(){
  2.                 _timer += Time.deltaTime;if(_timer >2f){
  3.                         _timer =0;
  4.                         Debug.Log("这是C#代码");}}}
复制代码
运行结果如下



现在我们希望通过热更新的方式修改Update方法,那么只需要在Lua脚本中调用xlua.hotfix()方法即可。该方法的第一个参数传入需要热更的C#类,第二个参数传入需要覆盖的方法名,第三个参数传递一个function,作为覆盖后的新方法。
  1. -- HotfixExample.lua.txtlocal class = CS.XLuaExample.HotfixExample
  2. local engine = CS.UnityEngine
  3. -- 允许访问私有成员
  4. xlua.private_accessible(class)
  5. xlua.hotfix(class,"Update",function(self)
  6.     self._timer=self._timer + engine.Time.deltaTime
  7.     if self._timer>2then
  8.         self._timer =0
  9.         engine.Debug.Log("这是Lua代码")endend)
复制代码
在运行结束前还需要将注入到C#方法的引用置空,所以再写一个置空的Lua脚本
  1. -- HotfixExampleDispose.lua.txt
  2. xlua.hotfix(CS.XLuaExample.HotfixExample,"Update",nil)
复制代码
然后再写个C#脚本模拟调用Lua脚本的入口
  1. publicclassStartLua:MonoBehaviour{privateLuaEnv _luaEnv;privatevoidAwake(){
  2.                 _luaEnv =newLuaEnv();
  3.                 _luaEnv.DoString("require 'HotfixExample'");}privatevoidOnDisable(){
  4.                 _luaEnv.DoString("require 'HotfixExampleDispose'");}privatevoidOnDestroy(){
  5.                 _luaEnv.Dispose();}}
复制代码
重新生成并注入代码后,运行项目,就会发现热更的Lua代码已经生效了



当然,在某些情况下我们只需要在原方法的基础上增加一点逻辑,而不是将方法完全覆盖。这时我们可以引入xLua中的util.lua脚本,并使用其提供的hotfix_ex()方法,实现增量热更
  1. local class = CS.XLuaExample.HotfixExample
  2. local engine = CS.UnityEngine
  3. xlua.private_accessible(class)local util = require 'util'
  4. util.hotfix_ex(class,"Update",function(self)-- 调用原本的方法
  5.     self.Update(self)if self._timer>1then
  6.         engine.Debug.Log("这是Lua代码")endend)
复制代码
效果如下



下面来总结一下热更新的流程
    首先我们在开发时应该在所有可能需要热更的类前加上[Hotfix]特性,在所有可能需要调用Lua脚本的地方加上[CSharpCallLua],在所有可能被Lua调用的地方加上[LuaCallCSharp],也可以通过反射实现。 如果真的需要热更新,那就通过编写Lua脚本覆盖所需的方法。Lua脚本应该有一个统一的入口集中加载。 最后将热更新的脚本、资源上传到服务器。玩家的客户端检查到更新后将热更新内容下载到本地,完成热更新。

本帖子中包含更多资源

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

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

本版积分规则

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

GMT+8, 2024-11-24 10:47 , Processed in 0.090228 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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