跳到主要内容

LuaAppDomain

LuaAppDomain 是 ZLua 的 唯一公开宿主入口:初始化 / 整域重置 Lua,以及用 GetFunction 从模块按名取得 Lua 函数对应的 Delegate。宿主面 暴露 Shutdown;清空脚本世界只走 Reset

Canonical 示例:zlua-demo Bootstrap.cs

API

namespace ZLua
{
public static class LuaAppDomain
{
public static void Initialize(Func<string, object> moduleLoader);
public static void Reset(Func<string, object> moduleLoader);

public static T GetFunction<T>(string luaModule, string luaMethodName)
where T : MulticastDelegate;
}
}

权威细则:spec/01-HOST-API.mdspec/10-LIFETIME.md §7。


Initialize(moduleLoader)

参数说明
moduleLoaderFunc<string, object>,按模块名返回 Lua 源码 stringbyte[]

仅首次(或进程内尚无主 lua_State)创建状态并安装 loader。已初始化时再次调用 → 抛异常(须 Reset再支持「只换 loader」)。

[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void InitZLuaOnStartup()
{
LuaAppDomain.Initialize(LoadLuaModule);
}

LoadLuaModule 负责 Editor(LuaScripts/*.lua)与 Player(StreamingAssets/*.lua.txt)路径差异,见 安装指南


Reset(moduleLoader)

热更或清空脚本世界:拆掉当前唯一主 lua_State,再以给定 loader 重建。

行为说明
调用当下仅预约:保存 loader;多次预约以最后一次为准。立刻 lua_close
真正执行本帧 EndOfFrameLuaFramePump / WaitForEndOfFrame):排空 pending ref → 关闭 Registry / 模块缓存 → lua_close → 按 Initialize 路径重建并安装 loader
旧委托EndOfFrame 应用之后,对旧 GetFunction 委托的调用 → 抛 C# 异常;宿主须重新 GetFunction 并丢弃字段缓存
Il2Cpp进程级 Bridge / XML 表 / InternalCall 保留,仅重建 state 级资源
// 热更后清空脚本世界(可在 C#↔Lua 调用中途调用;只排队)
LuaAppDomain.Reset(LoadLuaModule);
// 下一帧起:丢弃旧 Action/Func,重新 GetFunction

GetFunction<T>(luaModule, luaMethodName)

按模块名与方法名解析 Lua function,绑定为委托类型 T 并返回。

var add = LuaAppDomain.GetFunction<Func<int, int, int>>("app", "add");
int sum = add(10, 20);

var onTick = LuaAppDomain.GetFunction<Action<float>>("game", "OnTick");
onTick(0.016f);
规则说明
T必须是具体 MulticastDelegate 类型(如 Action<> / Func<>
luaModule / luaMethodNameLoadLuaModule 模块名、Lua return { ... } 键名一致
缓存由调用方负责(热路径请存到字段 / 局部变量后再调);Reset 生效后旧委托一律作废,须重新绑定
Marshal对返回的 delegate Invoke 时遵循 Marshal 速查表;可用 [LuaMarshalAs]

模块缺失、键不是 function、或无法绑定为 T → 抛 C# 异常。


初始化流程

双运行时转发

LuaAppDomain 本身在 ZLua.Common;实际逻辑由后端程序集实现:

环境程序集实现类型
Unity EditorZLua.MonoLuaMonoAppDomain
Il2Cpp PlayerZLua.Il2CppLuaIl2CppAppDomain

Application.isEditor 决定加载哪个后端;对外 API 不变

生命周期与 FramePump

初始化后会注册 LuaFramePump,在 Unity 帧循环中处理:

  • LateUpdate:ref / userdata 延迟释放(ProcessPendingRefReleases
  • WaitForEndOfFrame:执行已预约的 Reset(整域 teardown + 重建)

一般 无需 手动调用帧泵。

LuaEnv 的关系

类型可见性说明
LuaAppDomainpublic游戏代码唯一入口(Initialize / Reset / GetFunction
LuaEnvpublic(Mono 模块)底层 lua_State 包装;由后端内部创建,不建议业务代码自行 new LuaEnv()

标准集成路径:LuaAppDomain.InitializeGetFunction / CSharp 访问;热更清空用 Reset

模块加载约定

moduleLoader("app") 的返回值会被 require 语义加载。与 GetFunction(..., "app", ...)module 参数必须一致。

环境路径
Editor{ProjectRoot}/LuaScripts/app.lua
PlayerStreamingAssets/LuaScripts/app.lua.txt

常见错误

现象处理
Lua module loader is not configured未调用 Initialize 或 loader 为 null
再次 Initialize 抛异常已有主 state;改用 Reset(loader)
require / GetFunction 失败检查模块名、文件路径、.lua.txt 后缀、return 表键名
Reset 后旧委托抛异常丢弃缓存的 Action/Func,重新 GetFunction
Player 无 Lua 脚本确认 Sync 脚本已执行,StreamingAssets 含目标文件
Marshal / 绑定失败对照 Marshal 速查表T 签名

相关文档