You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何实现不阻塞主循环的对话系统?参考Fungus Lua实现

如何实现不阻塞主循环的对话系统?

刚好之前做过类似的非阻塞对话系统,结合你提到的Fungus风格,给你拆解下实现思路和具体代码:

核心原理:用Lua协程实现“暂停-恢复”逻辑

Lua的协程(Coroutines)是实现这种非阻塞对话的关键——它能让对话逻辑在需要等待用户输入时暂停,同时主循环依然正常处理渲染、输入检测等任务,完全不会卡住。

1. 实现基础的say对话函数

这个函数负责显示文本并等待用户确认,确认后再继续后续逻辑:

-- 全局变量管理对话协程
local dialogCoroutine = nil

-- 显示单行对话,支持两种语法:say("文本") 或 say "文本"
function say(text)
    -- 把文本传递给你的SayDialog UI组件(假设你已经有对应的UI实现)
    SayDialog:SetDisplayText(text)
    SayDialog:Show()

    -- 挂起协程,等待用户点击鼠标左键或按空格继续
    while not Input.GetMouseButtonDown(0) and not Input.GetKeyDown(KeyCode.Space) do
        coroutine.yield()
    end

    SayDialog:Hide()
end

2. 实现带选项的choose菜单函数

这个函数会显示选项列表,等待用户选择后返回对应的选项索引:

-- 显示选项菜单,返回用户选择的索引(从1开始)
function choose(options)
    -- 将选项列表填充到MenuDialog UI组件
    MenuDialog:SetOptions(options)
    MenuDialog:Show()

    local selectedIndex = nil
    -- 挂起协程,直到用户选中某个选项
    while selectedIndex == nil do
        -- 这里需要给每个选项按钮绑定点击事件,比如点击第n个选项时设置selectedIndex = n
        coroutine.yield()
    end

    MenuDialog:Hide()
    return selectedIndex
end

3. 启动对话流程的入口

把你的对话逻辑放到协程里启动,这样它就能和主循环并行执行:

-- 启动对话的入口函数
function StartStoryDialog()
    -- 创建并启动对话协程
    dialogCoroutine = coroutine.create(function()
        -- 这里就是你的对话脚本,和Fungus的写法完全一致
        say("Hi there")
        say "This syntax also works for say commands"
        
        local choice = choose{ "Go left", "Go right" }
        if choice == 1 then
            say("You chose left")
        elseif choice == 2 then
            say("You chose right")
        end
    end)
end

-- 在主循环里持续更新协程
function Update()
    -- 如果协程存在且未结束,就恢复执行
    if dialogCoroutine and coroutine.status(dialogCoroutine) ~= "dead" then
        coroutine.resume(dialogCoroutine)
    end
end

几个关键注意点

  • UI交互绑定choose函数里的选项按钮必须绑定点击事件,比如点击第i个选项时执行selectedIndex = i,这样协程才能恢复执行。
  • 协程清理:对话结束后可以把dialogCoroutine设为nil,避免无效的协程占用资源。
  • 语法糖支持:Lua本身就允许say "文本"这种省略括号的写法,只要函数只有一个字符串参数,不用额外处理。

内容的提问来源于stack exchange,提问作者John Smith

火山引擎 最新活动