一次性看懂Lua热更新原理与演示
了解了一下热更新机制。如果没有热更新,客户端代码修改后,用户获取新版客户端的步骤是这样的:下载客户端→等待下载→安装客户端→等待安装→启动游戏→等待加载→玩。
有了热更新之后,用户获取新版客户端的步骤变成了这样:启动游戏→等待热更新→等待加载→玩,省去了自行下载安装包并手动安装的步骤。
热更新是为了让用户获得资源和代码的变更。这里说的代码不是真正的二进制代码,用户不关心代码本身,他想要的是变化之后的业务逻辑,而Lua,就是实现热更新的主要机制。
使用Lua,需要先从GitHub上的xLua仓库下载Plugins文件夹和XLua文件夹,放入Unity项目的Assets目录下,导入成功后,Unity编辑器菜单栏会多出一个XLua选项。
下载插件的网址:( https://github.com/Tencent/xLua/tree/master/Assets )
接下来,我用一个最简单的案例来演示Lua热更新到底是怎么工作的。在Unity场景中创建两个UI按钮和一个UI文本组件,第一个按钮(targetButton)负责执行Lua函数,第二个按钮(reloadButton)负责重新加载Lua脚本,Lua文件的内容非常简单,只有几行:
function OnButtonClick()
return "Hello from Lua v1"
end
这个函数不做任何复杂的事情,只是返回一段文本,让场景中的Text组件显示出来。
C#脚本是核心,我把代码贴在下面:
public class LuaButtonHandler : MonoBehaviour
{
public Button targetButton;
public Button reloadButton;
public Text displayText;
private LuaEnv luaEnv;
private string luaFilePath;
private void Start()
{
luaEnv = new LuaEnv();
luaFilePath = Path.Combine(Application.streamingAssetsPath, "test.lua.txt");
LoadLuaFile(luaFilePath);
targetButton.onClick.AddListener(OnButtonClick);
reloadButton.onClick.AddListener(ReloadLua);
}
void LoadLuaFile(string luaFilePath)
{
string luaScript = File.ReadAllText(luaFilePath);
luaEnv.DoString(luaScript);
Debug.Log("Lua 文件加载成功: " + luaFilePath);
}
void ReloadLua()
{
Debug.Log("开始重载 Lua...");
string luaScript = File.ReadAllText(luaFilePath);
luaEnv.DoString(luaScript);
Debug.Log("Lua 重载成功!新逻辑已生效");
if (displayText != null)
{
string oldText = displayText.text;
displayText.text = "Lua 已重载!再次点击测试按钮查看变化";
// 2秒后恢复原来的文字(或保持提示)
StartCoroutine(RestoreDisplayTextAfterDelay(oldText, 2f));
}
}
IEnumerator RestoreDisplayTextAfterDelay(string originalText, float delay)
{
yield return new WaitForSeconds(delay);
if (displayText != null && displayText.text == "Lua 已重载!再次点击测试按钮查看变化")
{
displayText.text = originalText;
}
}
void OnButtonClick()
{
LuaFunction onClickFunc = luaEnv.Global.Get<LuaFunction>("OnButtonClick");
object[] result = onClickFunc.Call();
if (displayText != null)
{
displayText.text = result[0] as string;
}
}
void OnDestroy()
{
// 销毁 Lua 虚拟机,释放资源
if (luaEnv != null)
{
luaEnv.Dispose();
}
}
}
end
整个流程是这样的:在Start方法中,先创建一个LuaEnv环境,这是C#与Lua之间的桥梁,然后用LoadLuaFile读取并执行Lua文件,把里面的函数注册到Lua虚拟机中,targetButton绑定了OnButtonClick事件,每次点击按钮,C#会去Lua虚拟机里找到OnButtonClick这个函数并执行它,拿到返回值后显示在Text组件上,如下图所示。

reloadButton绑定了ReloadLua事件,它的作用是重新读取硬盘上的Lua文件,再次执行一遍,从而覆盖Lua虚拟机中的旧函数。
最精彩的部分来了,点击Unity的Play按钮运行游戏,先点击targetButton,Text会显示Lua文件中的返回值,也就是Hello from Lua v1。保持游戏处于运行状态,不要停止,打开Lua文件,把返回值修改成Hello from Lua v2,运行时热更新成功了,保存文件。回到Unity中运行的游戏窗口,点击reloadButton,控制台会输出重载成功的日志,最后,再次点击targetButton。你会发现,Text显示的内容,变成了你刚刚修改后的文字,如下图所示。

这就是Lua的精髓!让一个正在运行中的游戏,在不停止、不重新编译、不重新打包的情况下,获取到变化后的业务逻辑。
浙公网安备 33010602011771号