XLua教程之入门篇

发布于:2025-09-15 ⋅ 阅读:(15) ⋅ 点赞:(0)

简介

xLua 是腾讯开源的一个热更新解决方案,它为 Unity、.NET、Mono 等 C# 环境提供了与 Lua 脚本语言的无缝集成。其核心特点有:

支持热更新:在不重新发布客户端的情况下,修复 Bug 或更新游戏逻辑。

脚本化:将易变的业务逻辑用 Lua 编写,提高开发灵活性。

性能优秀:本身非常高效,且提供了强大的性能优化工具。

轻量高效:虚拟机轻量,绑定性能高。

无缝集成:C# 和 Lua 之间可以方便地互相调用,访问彼此的对象和函数。

强大的工具:提供 XLua.Hotfix 特性进行 C# 热补丁。

平台兼容:支持 Windows、macOS、Android、iOS 等全平台。

导入XLua

Github下载链接

https://github.com/Tencent/xLua

将下载的Xlua文件夹中的Plugins和XLua文件夹放入Assets文件夹中

查看左上角菜单栏是否有XLua按钮,说明是否导入成功

LuaEnv常用接口

在 C# 中,所有 Lua 操作都始于LuaEnv对象。

LuaEnv.Tick()

作用:手动触发 Lua 虚拟机的垃圾回收(GC)。在 Update中调用 luaEnv.Tick(),是使用 xLua 进行项目开发时一个非常重要的性能优化习惯。

说明

Lua 的自动垃圾回收机制
Lua 语言本身有一套自动垃圾回收机制,它会定期检查并释放不再使用的 Lua 对象(如 table、function、string 等)占用的内存。这个“定期”是由 Lua 虚拟机内部控制的,它根据内存分配的增长速度等启发式算法来决定何时运行。

xLua 在 Unity 中的默认行为:
在 xLua 中,默认情况下,Lua 虚拟机的全量垃圾回收(Full GC)是与 Mono 或 IL2CPP 的垃圾回收同步的。也就是说,通常会在 Unity 的 C# GC 发生时(或者帧末等时机),xLua 会自动调用一次 LuaGC.LuaGCMode.Forced 模式的 GC,这可能会带来不可控的卡顿。

Tick() 方法的引入:
为了给开发者提供更精细、更可控的性能管理手段,xLua 提供了 LuaEnv.Tick() 方法。调用 Tick() 会手动触发一次 Lua 虚拟机增量的一步垃圾回收。它不是一次性的、全量的垃圾回收,而是每次调用只进行一小步回收工作。这可以将一次可能引起卡顿的完整 GC 过程,分摊到多帧中去完成。

使用 Tick(),你可以这样做:

void Update() {
    // 每帧执行一次Lua的增量GC
    luaEnv.Tick();
}

通过每帧调用 Tick(),你将 Lua 的 GC 工作量均匀地分摊到了每一帧。虽然每一帧都有一点点开销,但避免了单帧的严重卡顿,使得帧时间更加平稳,游戏体验更流畅。

LuaEnv.Dispose()

作用:释放、清理和销毁 LuaEnv 实例所占用的资源,防止内存泄露。

每一个 new LuaEnv() 都必须有一个与之对应的 luaEnv.Dispose()。最安全、最常用的地方就是在 Unity 的 OnDestroy生命周期方法中调用。

void OnDestroy()
{
    if (luaEnv != null)
    {
        luaEnv.Dispose();
        luaEnv = null;
    }
}

LuaEnv.DoString(str)

1、执行Lua语句

执行一个字符串str,字符串str内容必须符合Lua语法

LuaEnv luaEnv = null;
void Start()
{
    luaEnv = new LuaEnv();
    luaEnv.DoString("print('hello world')");
}

void Update()
{
    // 每帧进行增量GC,平滑分摊GC开销
    if (luaEnv != null)
    {
        luaEnv.Tick();
    }
}

void OnDestroy()
{
    //在对象被销毁时,清理Lua环境
    if (luaEnv != null)
    {
        luaEnv.Dispose();
        luaEnv = null; // 将其置为null是一个好习惯,防止后续误用
    }
}

2、加载Lua模块(不推荐)

调用路径默认在Resources下,即只能加载放在Unity的Resources文件夹下的lua脚本。并且,lua脚本后缀必须为.lua.txt   

建议使用LuaEnv.AddLoader来加载脚本

例如:加载First.lua.txt脚本

 luaEnv.DoString("require ('First')");

LuaEnv.AddLoader

Lua脚本路径重定向,用于从指定的lua脚本路径进行加载。

luaEnv.AddLoader(CustomLoader);
luaEnv.DoString("require ('Main')");


public byte[] CustomLoader(ref string filepath)  
{
    //传入的参数是require执行的脚本文件名
    string path = Application.dataPath + "/LuaScripts/" + filepath + ".lua.txt";

    if (File.Exists(path))//判断该路径是否存在
    {
        return File.ReadAllBytes(path);
    }
    else
    {
        Debug.Log("未找到该文件!");
    }

    return null;
}

LuaEnv启动模板

public class LuaLauncher : MonoBehaviour
{
    LuaEnv luaEnv = null;
    
    void Start()
    {
        luaEnv = new LuaEnv();
        luaEnv.AddLoader(CustomLoader);
        luaEnv.DoString("require ('Main')");
    }
    
    public byte[] CustomLoader(ref string filepath)  
    {
        //传入的参数是require执行的脚本文件名
        string path = Application.dataPath + "/LuaScripts/" + filepath + ".lua.txt";

        if (File.Exists(path))//判断该路径是否存在
        {
            return File.ReadAllBytes(path);
        }
        else
        {
            Debug.Log("未找到该文件!");
        }
        return null;
    }
    
    void Update()
    {
        // 每帧进行增量GC,平滑分摊GC开销
        if (luaEnv != null)
        {
            luaEnv.Tick();
        }
    }

    void OnDestroy()
    {
        //在对象被销毁时,清理Lua环境
        if (luaEnv != null)
        {
            luaEnv.Dispose();
            luaEnv = null; // 将其置为null是一个好习惯,防止后续误用
        }
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到