跳到主要内容

为什么选择 ZLua

xLua、toLua、SLua 已经证明「在 Unity 里用 Lua」可行。ZLua 要解决的是下一层问题:把 Lua↔C# 做成真正现代、完备、且在 Il2Cpp 上足够快、足够省的互操作——而不是再堆一套配置、白名单和海量 Wrap。

详细矩阵见 选型对比;迁移见 migration


七个理由(30 秒)

一句话
更易用设计更现代;极度简单;零配置(无需 per-type C# Wrap 白名单)
更完备标准、完备的 C#↔Lua 交互,几乎覆盖全部常用 C# 特性
更高效98.2% 对齐用例快于 xLua;Lua→C# 平均约 2.62×;常见字段/属性/调用约
更少更快的 GC引用类型与 struct(含含引用字段的 struct)默认 0 GC;另有 OpaqueValue 等策略
极小的桥接同签名合并 + 直接生成高效 C++;体积可小一个数量级;支持 0 桥接函数 仍保持高性能
版本更广Lua 5.1–5.5LuaJIT(Il2Cpp 上 JIT 仅 Android / iOS);Unity 2021+团结引擎
维护更积极全职专业团队;Bug 响应与特性迭代更快

1. 更易用:现代、简单、零配置

传统方案的心智负担往往是:

  • 维护 LuaCallCSharp / 导出列表
  • 改 API 就要重新 Generate 海量 C# Wrap
  • C#→Lua 走命令式 LuaEnv / GetInPath / Call

ZLua 把互操作做成接近 P/Invoke 的声明式模型:

你要做的事ZLua
C# 调 LuaLuaAppDomain.GetFunction<T>(…) 取得 Delegate 后 Invoke
覆盖 Marshal[LuaMarshalAs]
Lua 访问 C#CSharp 根表懒加载,无需为每个类型写 Wrap 配置
// 须在 Initialize 之后(例如 Awake),勿用 static 字段初始化器
var AppAdd = LuaAppDomain.GetFunction<Func<int, int, int>>("app", "add");
// AppAdd(10, 20);
CSharp['AC'] = CSharp['Assembly-CSharp']
print(CSharp.AC.Demo.Add(3, 5))

零配置指:不需要 per-type C# Wrap 白名单与成员级 Wrap 工程。Editor 开箱即用;发 Il2Cpp Player 时执行一次 ZLua/Generate/All(生成 C++ stub,不是 xLua 式 C# Wrap)。

快速开始 · 使用指南


2. 更完备:几乎能调到的 C# 都能调

目标不是「导出几个热路径 API」,而是 标准和完备的 C#↔Lua 交互,包括但不限于:

类别能力
类型class / struct / interface / enum / nullable
成员静态与实例:字段、属性、方法
高级泛型类、泛型方法、delegate、数组(含多维)
语言细节方法重载、ref / out / in、Event(add_ / remove_

语义以 规范 为契约;双端(Mono Editor / Il2Cpp Player)Lua 可见行为一致

兼容性矩阵 · 特性对比


3. 更高效:不是「理论上快一点」

Il2Cpp Win64 Release 上四方对齐基准(公开仓库 zlua-benchmark;说明见 PERFORMANCE):

指标结果(相对 zlua 的平均 ratio,>1 更慢)
Lua→C#(231 cases)xLua ≈ 2.57×;toLua ≈ 3.52×;SLua ≈ 7.68×
C#→Lua(54 cases)xLua ≈ 1.59×;toLua ≈ 3.27×;SLua ≈ 14.9×
相对 xLua 领先比例98.6% 用例(281/285)
常见字段 / 属性3.5–4×(相对 xLua)

完整报告:comparison_20260728_121554.md

根因很直接:去掉 libxlua 折返 + 海量 C# Wrap,在 C++ 里一次完成 marshal 与 methodPointer 调用。

提示

互调再快,也要先 profiling。若脚本边界只占帧时间 2%,五倍互调也只省约 1.6%。ZLua 适合 战斗公式、UI、每帧大量小调用 这类边界热点。

性能对比


4. 更少更快的 GC

默认策略面向热路径:

策略含义
引用类型默认走对象表 / userdata,避免无意义装箱与临时 object[]
struct无论字段中是否含引用类型,默认可走 0 GC Marshal 路径(ByVal / ByObj 等,见规范)
OpaqueValuelightuserdata 临时句柄:同步调用链内更灵活的低分配策略
enum默认 integer,不强制 boxed userdata

需要写回时用 Opaque / ByVal userdata;裸 number 不回写(与 C# ref 语义对齐,见 ref/out/in)。

GC 对比 · 生命周期规范


5. 极小的 wrapper / 桥接:可小一个数量级,可至 0

方案典型体积模型
xLua / toLua / SLua每类型 / 每成员 生成 Wrap,体积近似随导出成员线性膨胀
ZLua(Il2Cpp)合并同签名 桥接函数,直接生成高效 C++ stub(ReducedType 复用)

因此在「仍能访问几乎全部 C# 类型、字段、属性、方法」的前提下:

  • 桥接代码体积通常比传统方案 小一个数量级以上
  • 支持 0 桥接函数 配置;即便如此,交互性能仍可高于「生成大量 Wrap」的传统路径

Editor(Mono)用 Expression Emit,不进 Player 包;Player 体积由 C++ stub 决定。

桥接与体积


6. 支持的 Unity 与 Lua 更多

维度ZLua
Lua5.1 – 5.5LuaJIT(Settings 默认 lua-5.5.0;LuaJIT 的 Il2Cpp 发布 仅 Android / iOS
Unity2021.32022.3Unity 6(6000.0 / 6000.3 / 6000.5)
引擎团结引擎

多版本意味着更少「卡在某个 Lua/Unity 组合」的选型风险。完整矩阵见 兼容性

支持的版本与平台


7. 维护更积极

ZLua 由 全职专业团队 维护:

  • Bug 响应更积极
  • 特性与规范迭代更快
  • 文档、基准与包内 Docs 同源演进

适合把 Lua 互操作当作 长期基础设施,而不是「停更的第三方插件」。


不适合选 ZLua 的情况

诚实边界同样重要:

情况建议
不愿维护 libil2cpp 集成插件形态的 xLua / toLua 更轻
强依赖 xLua Hotfix 管线继续使用 xLua
已有大量 xLua 资产、短期无迁移预算先读 从 xLua 迁移

下一步

  1. 5 分钟快速开始 + zlua-demo
  2. 性能对比 · GC · BRIDGE
  3. 特性对比
  4. 规范总览

延伸阅读

文档内容
设计概览GetFunction 与双向桥接
双运行时Mono / Il2Cpp 分工
术语表Opaque / ByVal / stub 等
Il2Cpp 实现Player 模块图