lua协程 - 把回调模式的代码流程改成顺序执行流程
像ugui的点击按钮,然后触发相关逻辑,都是回调模式的写法,比如下面代码的ShowAlert调用
public class Test7 : MonoBehaviour { public GameObject m_Alert; public Text m_TxtMsg; public Button m_BtnYes; public Button m_BtnNo; private LuaEnv m_LuaEnv; void Start() { m_LuaEnv = new LuaEnv(); m_LuaEnv.AddLoader((ref string filePath) => { filePath = filePath.Replace('.', '/'); filePath = $"Assets/{filePath}.lua.txt"; var txtAsset = AssetDatabase.LoadAssetAtPath<TextAsset>(filePath); return Encoding.UTF8.GetBytes(txtAsset.text); }); m_LuaEnv.Global.Set("Test7MonoInst", this); m_LuaEnv.DoString("require('Lua.Test7')"); } void OnDestroy() { if (null != m_LuaEnv) m_LuaEnv.Dispose(); } //注意: Test7GenConfig不写, lua在调用该函数时无法识别Action<int> public void ShowAlert(string msg, Action<int> cb) { m_Alert.SetActive(true); m_TxtMsg.text = msg; m_BtnYes.onClick.AddListener(() => { if (null != cb) cb(1); m_BtnYes.onClick.RemoveAllListeners(); m_BtnNo.onClick.RemoveAllListeners(); m_Alert.SetActive(false); }); m_BtnNo.onClick.AddListener(() => { if (null != cb) cb(-1); m_BtnYes.onClick.RemoveAllListeners(); m_BtnNo.onClick.RemoveAllListeners(); m_Alert.SetActive(false); }); } }
下面的是代码Gen配置(一定要写),同时还要生成下代码才行,否则lua代码没法正确执行
public static class Test7GenConfig { [LuaCallCSharp] public static List<Type> LuaCallCsList = new List<Type>() { typeof(Action), //这个默认的不写, 下面的Action<int>会不生效 typeof(Action<int>), }; }
下面的lua代码通过协程将ShowAlert的调用改成顺序执行,而不是通过提供回调函数
function ShowAlert(msg, cb) Test7MonoInst:ShowAlert(msg, cb) end function SyncWrap(func, msg) local coThread, isMain = coroutine.running() if isMain then error("no in coroutine") return end local cb = function(btn) --点击按钮时, 从暂停位置1继续 local flag, coReturn = coroutine.resume(coThread, btn) end func(msg, cb) local resumeParam = coroutine.yield() --暂停位置1 local btn = resumeParam return btn end local coFunc = function() local btn = SyncWrap(ShowAlert, "确定要退出吗?") if 1 == btn then print("点击了Yes") elseif -1 == btn then print("点击了No") end end local coThread = coroutine.create(coFunc) local flag, coReturn = coroutine.resume(coThread)
SyncWrap更通用的写法
function SyncWrap(func, ...) local coThread, isMain = coroutine.running() if isMain then error("no in coroutine") return end local cb = function(btn) --点击按钮时, 从暂停位置1继续 local flag, coReturn = coroutine.resume(coThread, btn) end local funcParams = { ... } table.insert(funcParams, cb) func(unpack(funcParams)) local resumeParams = { coroutine.yield() } --暂停位置1 local rets = unpack(resumeParam) return rets end
分类:
lua
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!