b[toc]
# 连接
https://github.com/smilehao/xlua-framework
# XLuaManager
先预定义了几个常量
1 2 3 4 5
| public const string luaAssetbundleAssetName = "Lua"; public const string luaScriptsFolder = "LuaScripts"; const string commonMainScriptName = "Common.Main"; const string gameMainScriptName = "GameMain"; const string hotfixMainScriptName = "XLua.HotfixMain";
|
定义两个 Lua 运行时变量
1 2
| LuaEnv luaEnv = null; LuaUpdater luaUpdater = null;
|
初始化 XLuaManager
函数中
1 2 3 4 5 6 7 8 9 10
| protected override void Init() { base.Init(); string path = AssetBundleUtility.PackagePathToAssetsPath(luaAssetbundleAssetName); AssetbundleName = AssetBundleUtility.AssetBundlePathToAssetBundleName(path); InitLuaEnv(); }
|
初始化 Lua 环境
其中这一步中 CustomLoader 是自定义的 Lua 文件字节读取函数,可以看下它本身的实现,本质上就是在 Assetbundle 下读取所有的 lua script luaEnv.AddBuildin 这局本质上加载 protobuf - Lua, 文档上说是加载的 ToLua 里的 Proto-gen-lua
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public bool HasGameStart { get; protected set; }
void InitLuaEnv() { luaEnv = new LuaEnv(); HasGameStart = false; if (luaEnv != null) { luaEnv.AddLoader(CustomLoader); luaEnv.AddBuildin("pb", XLua.LuaDLL.Lua.LoadPb); } else { Logger.LogError("InitLuaEnv null!!!"); } }
|
OnInit()
这个是在资源管理器加载完 Lua AB 包以后才会调用
先调用 LoadScript (MainLuaName) 启动 Lua 的入口
然后初始化 LuaUpdater, 启动 Lua 循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public void OnInit() { if (luaEnv != null) { LoadScript(commonMainScriptName); luaUpdater = gameObject.GetComponent<LuaUpdater>(); if (luaUpdater == null) { luaUpdater = gameObject.AddComponent<LuaUpdater>(); } luaUpdater.OnInit(luaEnv); } }
|
Restart () 重启虚拟机
- 停止热更
- 释放资源
- 重新初始化 Lua 环境
- 重新初始化 Lua 层
1 2 3 4 5 6 7 8 9
|
public void Restart() { StopHotfix(); Dispose(); InitLuaEnv(); OnInit(); }
|
SafeDoString(LuaScript)
安全的执行 Lua 脚本,传递进来的是 Lua 脚本内容,就是套了层 Try - Catch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public void SafeDoString(string scriptContent) { if (luaEnv != null) { try { luaEnv.DoString(scriptContent); } catch (System.Exception ex) { string msg = string.Format("xLua exception : {0}\n {1}", ex.Message, ex.StackTrace); Logger.LogError(msg, null); } } }
|
StartHotfix 开启 Lua 热更
如果是重启状态,则重启热更,否则 Lua 层开始执行热更 Lua 模块的主函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public void StartHotfix(bool restart = false) { if (luaEnv == null) { return; }
if (restart) { StopHotfix(); ReloadScript(hotfixMainScriptName); } else { LoadScript(hotfixMainScriptName); } SafeDoString("HotfixMain.Start()"); }
public void StopHotfix() { SafeDoString("HotfixMain.Stop()"); }
|
StartGame,Lua 层的启动游戏,在 Lua 初始化完成后调用
1 2 3 4 5 6 7 8 9
| public void StartGame() { if (luaEnv != null) { LoadScript(gameMainScriptName); SafeDoString("GameMain.Start()"); HasGameStart = true; } }
|
Update 中的处理
每 100 帧清一下 Lua 的 GC, 且每帧都要调一下 Lua 的 Tick
1 2 3 4 5 6 7 8 9 10 11 12
| private void Update() { if (luaEnv != null) { luaEnv.Tick();
if (Time.frameCount % 100 == 0) { luaEnv.FullGc(); } } }
|
OnLevelWasLoaded 新场景加载进入时调用
1 2 3 4
| if (luaEnv != null && HasGameStart) { SafeDoString("GameMain.OnLevelWasLoaded()"); }
|