Lua 基础语法(五)Unity xLua基础配置与 C# 访问 Lua

核心知识点:主流 Lua 热更插件对比、xLua 导入配置、Hotfix 宏、LuaEnv 解释器、DoString/Require、自定义 Loader 加载器、全局变量读取、Lua 表 5 种映射方式、委托映射 Lua 函数、桥接代码生成、值拷贝与引用修改区别

一、市面 Unity Lua 热更新插件选型

1 概念

Unity 生态多款 Lua‑C# 交互插件,xLua、SLua、ToLua、ULua、NLua;底层都是在原生 LuaInterface 基础上做 Unity 适配扩展。

2 特性 & 规则

  1. ToLua:曾经国内项目大量使用,开发公司倒闭,停止维护。

  2. SLua / ULua:维护活跃度低,新版本 Unity 适配差。

  3. NLua:仍有少量维护,但生态案例少。

  4. xLua(腾讯)【课程选用】 腾讯开源,趋于稳定,工业项目广泛使用; 最大优势:Hotfix 热补丁,已经写好的 C# 代码,线上出 Bug 可以直接用 Lua 打补丁修复; 其它 Lua 插件要求业务前期全部用 Lua 写;xLua 允许主力业务 C# 开发,只 Bug 修复用 Lua; C# 编译执行性能远高于 Lua,主力逻辑 C# 保证性能,热更部分交给 Lua。

  5. ILRuntime:C# 代码热更,不支持 iOS 平台热更新,商业项目使用变少。

热更新价值:不需要下载完整安装包,不需要应用商店审核,只更新脚本资源;风险:Lua 脚本可以执行任意逻辑,存在恶意代码风险。

4 相关知识点对比

表格

插件 维护状态 核心特点
ToLua 停止维护 老项目存量多,新项目不推荐
SLua/ULua 低活跃度 适配新版本 Unity 麻烦
xLua (腾讯) 稳定成熟 支持 Hotfix 补丁,C# 可写主力业务
ILRuntime 活跃 C# 热更,iOS 平台禁止热更

5 模块拓展

xLua 只是工具,真正热更新还需要配合 AB 包下载、本地持久目录。

二、xLua 导入工程与环境配置

1 概念

把 xLua 源码包导入 Unity,配置脚本宏、补充 dll,完成基础环境。

2 特性 & 规则

  1. 复制AssetsTools文件夹到项目对应目录;删除 Examples 示例文件夹避免版本报错。

  2. Player Settings → Other Settings → Scripting Define Symbols 添加宏:HOTFIX_ENABLE,回车确认开启热补丁功能。

  3. 复制 Unity 安装目录下这 3 个 dll:UnityEngine.dllUnityEngine.mdbUnityEngine.pdb,放到Assets/xLua/src/Editor目录。

  4. 项目路径禁止中文,否则 xLua 编译、生成桥接代码会报错。

  5. 配置成功后 Unity 顶部菜单栏多出XLua菜单项。

3 语法 & 操作要点

编辑器菜单:XLua → Generate Code(生成桥接代码);XLua → Hotfix Inject In Editor(注入热补丁)。

4 相关知识点对比

缺少 HOTFIX_ENABLE 宏:Hotfix 全部功能不可用。

5 模块拓展

桥接生成代码放在Assets/XLua/Gen文件夹。

三、LuaEnv 解释器基础,DoString 执行 Lua 代码

1 概念

LuaEnv是 xLua 核心解释器实例,和原生 LuaInterface 的 LuaEnv 原理几乎一致;DoString()直接执行字符串形式 Lua 代码。

2 特性 & 规则

  1. using XLua;引入命名空间;

  2. LuaEnv luaEnv = new LuaEnv();创建解释器;

  3. DoString 传入字符串执行 Lua 脚本;

  4. Lua 中访问 C# 类必须写完整命名空间,格式:cs.命名空间.类名;示例:cs.UnityEngine.Debug.Log("xxx")

3 语法 & 代码片段

复制代码
using XLua;
LuaEnv luaEnv = new LuaEnv();
//执行Lua字符串代码
luaEnv.DoString(@"
    print(""hello lua"")
    cs.UnityEngine.Debug.Log(""C#输出,来自Lua调用"")
");

4 相关知识点对比

原生 LuaInterface VS xLua LuaEnv

底层原理一致;xLua 做了 Unity 适配、增加 Hotfix、桥接生成工具。

5 模块拓展:DoString 适合小段测试,正式业务用文件加载。

四、Lua 脚本加载:Resources + Require + 自定义 AddLoader 加载器

1 概念

三种加载 Lua 脚本方式:Resources 加载、require、AddLoader 自定义加载器。

lua 脚本文件命名规范:xxx.lua.txt,Resources.Load 读取时后缀.txt省略,直接写xxx.lua

2 特性 & 规则

  1. require:默认从Resources目录查找脚本;require 加载过的脚本会缓存,不会重复执行。

  2. 缺陷:Resources 打包之后资源不能修改;热更新下载到PersistentDataPath / StreamingAssets的脚本 require 默认读不到。

  3. luaEnv.AddLoader(委托)注册自定义加载器;自定义加载器可以从任意磁盘路径读取 lua 文本字节数组,实现热更新加载外部下载的 lua 脚本。

3 语法 & 代码片段

复制代码
//自定义加载器,读取StreamingAssets下面的lua文件
luaEnv.AddLoader((ref string filename) =>
{
    string path = System.IO.Path.Combine(Application.streamingAssetsPath, filename + ".lua.txt");
    if(System.IO.File.Exists(path))
    {
        string text = System.IO.File.ReadAllText(path);
        return System.Text.Encoding.UTF8.GetBytes(text);
    }
    return null;
});
//注册完自定义Loader之后,require就可以加载外部路径脚本
luaEnv.DoString(@"require('test')");

4 相关知识点对比

require 默认加载 VS AddLoader 自定义加载器

require 默认:只能 Resources,打包不可修改,不适合热更; AddLoader:自定义任意磁盘路径,支持 PersistentDataPath 下载后的热更脚本。

5 模块拓展:AB 包解压 lua 脚本到 PersistentDataPath,配合 AddLoader 加载实现热更。

五、C# 读取 Lua 全局变量

1 概念

luaEnv.Global全局表对象,Get<T>("变量名") 读取 Lua 全局变量。

2 特性 & 规则

  1. 指定泛型 T 匹配 Lua 数据类型:double、string、bool;

  2. 参数是 Lua 脚本中全局变量名字符串;局部 local 变量 C# 无法读取。

3 语法 & 代码片段

复制代码
luaEnv.DoString(@"
    a = 100
    name = ""玩家测试""
    flag = true
");
double a = luaEnv.Global.Get<double>("a");
string name = luaEnv.Global.Get<string>("name");
bool flag = luaEnv.Global.Get<bool>("flag");

4 相关知识点对比

local 局部变量 VS 全局变量

local 局部:脚本内部有效,Global 拿不到; 不加 local 才是全局,可以 C# 读取。

5 模块拓展:nil 读取得到 C# 的 null。

六、C# 映射 Lua Table 的 5 种方式

1 概念

xLua 提供 5 种方式接收 Lua table,各有适用场景:映射普通 Class、映射 Interface、Dictionary、List、原生 LuaTable。

2 特性 & 规则

  1. 映射普通 C# Class(最常用,只读值拷贝) table 字段和 C# 类成员名字一一对应; C# 修改对象,不会反向修改 Lua 原表,属于值拷贝只读。

  2. 映射 Interface(桥接,双向读写) 接口中只能写属性,不能写字段 ; 接口标记[CSharpCallLua];XLua 菜单 Generate Code 生成桥接 Gen 代码; C# 修改接口属性,会同步修改 Lua 原始 table;双向可读写。

  3. Dictionary<string,object> :只读取 table 字符串 key 键值对;数组下标数字 key 无法读取

  4. List<object> :只读取 table连续数组下标部分,哈希字符串 key 读取不到。

  5. LuaTable 原生对象:xLua 原生表对象;性能差,项目尽量少用。

3 语法 & 代码片段

复制代码
//lua脚本
luaEnv.DoString(@"
person = {
    name = ""张三"",
    age = 20,
    100,200,300
}
");
//1、映射普通class(只读,值拷贝)
public class Person
{
    public string name;
    public int age;
}
Person p = luaEnv.Global.Get<Person>("person");
​
//2、映射Interface(双向读写,需要CSharpCallLua标签,生成桥接代码)
[CSharpCallLua]
public interface IPerson
{
    string name { get; set; }
    int age { get; set; }
}
IPerson ip = luaEnv.Global.Get<IPerson>("person");
​
//3、Dictionary读取字符串key
Dictionary<string,object> dict = luaEnv.Global.Get<Dictionary<string,object>>("person");
​
//4、List读取数组下标元素
List<object> list = luaEnv.Global.Get<List<object>>("person");
​
//5、原生LuaTable
LuaTable lt = luaEnv.Global.Get<LuaTable>("person");

4 相关知识点对比

普通 Class 映射 VS Interface 桥接映射

Class:值拷贝,只读;C# 修改不影响 Lua 源表;不需要生成桥接代码; Interface:引用桥接,双向读写;必须标记[CSharpCallLua]+Generate Code 生成桥接文件。

5 模块拓展:游戏配表读取优先使用 Class 映射。

七、C# 调用 Lua 函数:委托映射(CSharpCallLua)

1 概念

Lua 全局函数 /table 内部函数,C# 侧定义委托,打上[CSharpCallLua]标签,Generate Code 生成桥接,接收 Lua 函数;支持多返回值用 out 参数接收。

2 特性 & 规则

  1. 委托标记[CSharpCallLua];执行 XLua Generate Code 生成桥接;

  2. table 内部的成员函数映射接口里面的委托;冒号:调用会自动传入 self 参数;

  3. Lua 多返回值,C# 委托使用out输出参数接收。

3 语法 & 代码片段

复制代码
//委托标记标签
[CSharpCallLua]
public delegate int CalcFunc(int a,int b,out int subRes);
​
//lua脚本
luaEnv.DoString(@"
function Calc(a,b)
    return a+b, a-b
end
");
CalcFunc calc = luaEnv.Global.Get<CalcFunc>("Calc");
int addRes = calc(1,2,out int subRes);

4 相关知识点对比

委托映射 VS 原生 LuaFunction

委托:类型安全,性能高,业务首选; LuaFunction:原生对象,性能差,项目尽量规避。

5 模块拓展:table 里面的函数通过接口内委托映射访问。

综合拓展

1 流程 xLua 导入→配置 HOTFIX_ENABLE 宏→补充 dll→LuaEnv 实例→DoString 测试代码→三种脚本加载方式(Resources/require/AddLoader 自定义加载器)→Global 读取全局变量→table 五种映射方式→委托映射 Lua 函数,理解 Class 只读拷贝、Interface 双向桥接区别。

2 高频 Bug 排查清单

  1. xLua 菜单不出现:文件没有完整导入,或者脚本放在非 Editor 目录;

  2. require 读不到热更脚本:没有实现 AddLoader 自定义加载器;

  3. Interface 映射报错:忘记打[CSharpCallLua]标签,没有执行 Generate Code 生成桥接代码;

  4. C# 修改 class 映射对象 Lua 表不变:class 是值拷贝只读,要用 Interface;

  5. 项目报错中文路径:工程路径存在中文,xLua 生成桥接失败。

3 核心考点 xLua 相比其它 Lua 插件优势、Hotfix 补丁概念、LuaEnv 解释器、require 机制、AddLoader 自定义加载器作用;table 五种映射方式区别;[CSharpCallLua]标签、Generate Code 桥接代码;Class 值拷贝只读 VS Interface 双向读写;委托映射 Lua 函数多返回 out 参数。

4 进阶拓展学习方向 Lua 调用 C# 类、Hotfix 热补丁、AB 包 + PersistentDataPath 完整热更新 Demo。

相关推荐
淼澄研学1 小时前
Sonos空间音频技术解析与Python本地API控制实操
开发语言·python·音视频
研☆香1 小时前
js中使用的正则表达式
开发语言·javascript·正则表达式
szarron1 小时前
国产手持式频谱分析仪选型攻略:TFN RC系列 vs HTOOL SA8T频谱分析仪 专业参数对比(军工/路测/调试全覆盖)
开发语言·前端·状态模式
我是唐青枫1 小时前
C#.NET StructureMap 从依赖注入到项目实战
开发语言·c#·.net
Beyond_System|系统之外1 小时前
一个网页如何同时适配投影仪、1366×768 和 1920×1080?我重新理解了“自适应布局”
开发语言·css·html
z落落1 小时前
C#简易聊天室(服务器+客户端)
运维·服务器·c#
dcrenl1 小时前
C# 程序发布时加入发布时间
c#·版本号·发布时间
Wang's Blog2 小时前
Java框架快速入门: Spring Security+OAuth2之定制登录页
java·开发语言·spring
imgsq2 小时前
MapLibre GL JS v6 正式发布:v5 之后八个月的第一个大版本(编译)
开发语言·javascript·ecmascript