Lua 协程(Coroutine):游戏里的“伪多线程”利器

🧩 一、先说结论:协程解决什么问题?

在游戏开发中,你一定写过这种逻辑:

  • 技能释放 → 等1秒 → 再造成伤害
  • 播放动画 → 等动画结束 → 再执行下一步
  • 打字效果 → 一点一点显示

❌ 传统写法(回调地狱)

lua 复制代码
playAnimation(function()
    delay(1, function()
        doDamage()
    end)
end)

👉 问题:

  • 可读性差 ❌
  • 嵌套地狱 ❌
  • 难维护 ❌

✅ 协程写法(像同步一样写异步)

lua 复制代码
function skill()
    playAnimation()
    wait(1)
    doDamage()
end

👉 优点:

  • 逻辑直观 ✔
  • 易维护 ✔
  • 更像"线性流程" ✔

🧠 二、协程到底是什么?

你可以把协程理解为:

👉 "可以随时暂停 / 恢复的函数"


🚀 三、核心API(必须掌握)


🎯 1. 创建协程

lua 复制代码
co = coroutine.create(function()
    print("开始")
end)

🎯 2. 启动协程

lua 复制代码
coroutine.resume(co)

🎯 3. 暂停(关键)

lua 复制代码
coroutine.yield()

👉 流程是这样的:

复制代码
resume → 执行 → yield → 停住
再次 resume → 从停的位置继续

🔥 四、最经典例子(必须看懂)

lua 复制代码
co = coroutine.create(function()
    print("A")
    coroutine.yield()
    print("B")
end)

coroutine.resume(co)  -- 输出 A
coroutine.resume(co)  -- 输出 B

👉 执行过程:

复制代码
第一次 resume → A → yield(暂停)
第二次 resume → B

🎮 五、游戏实战:技能延迟释放


❌ 普通写法(很乱)

lua 复制代码
function castSkill()
    playAnim()

    delay(1, function()
        doDamage()
    end)
end

✅ 协程写法(推荐)

lua 复制代码
function castSkill()
    playAnim()
    coroutine.yield(1)  -- 等1秒
    doDamage()
end

👉 问题来了:

Lua原生 不支持"时间等待"

👉 所以我们要自己实现一个 👇


🔥 六、手写一个"协程调度器"(重点)

这是游戏开发中非常常见的设计👇


🧩 1. 调度器结构

lua 复制代码
Scheduler = {
    tasks = {}
}

🧩 2. 添加任务

lua 复制代码
function Scheduler:add(co)
    table.insert(self.tasks, {
        co = co,
        wait = 0
    })
end

🧩 3. 更新(每帧调用)

lua 复制代码
function Scheduler:update(dt)
    for i = #self.tasks, 1, -1 do
        local task = self.tasks[i]

        if task.wait > 0 then
            task.wait = task.wait - dt
        else
            local ok, waitTime = coroutine.resume(task.co)

            if not ok then
                table.remove(self.tasks, i)
            elseif waitTime then
                task.wait = waitTime
            else
                table.remove(self.tasks, i)
            end
        end
    end
end

👉 关键点:

lua 复制代码
coroutine.yield(1)

👉 相当于:

👉 "暂停1秒后再继续"


🎮 七、完整技能示例(真实项目级)

lua 复制代码
function skill()
    print("播放动画")
    coroutine.yield(1)

    print("造成伤害")
    coroutine.yield(0.5)

    print("播放特效")
end

local co = coroutine.create(skill)
Scheduler:add(co)

👉 游戏主循环:

lua 复制代码
function update(dt)
    Scheduler:update(dt)
end

👉 效果:

复制代码
0s: 播放动画
1s: 造成伤害
1.5s: 播放特效

🧠 八、协程在游戏中的真实用途


🎯 1. 技能系统

  • 延迟伤害
  • 连击技能
  • 持续效果

🎯 2. UI系统

  • 打字机效果
  • 渐显动画
  • loading流程

🎯 3. 剧情系统

  • 对话播放
  • 镜头切换
  • 事件串联

👉 一句话总结:

🔥 所有"有时间流程"的逻辑,都可以用协程写


⚠️ 九、常见坑(一定要知道)


❗ 1. 忘记 resume

👉 协程不会自动执行 ❌


❗ 2. yield 只能在协程里用

lua 复制代码
coroutine.yield()  -- 主线程会报错 ❌

❗ 3. 死循环卡死

lua 复制代码
while true do
    -- 没有 yield
end

👉 会直接卡死游戏 ❌


🔥 十、高手用法(进阶理解)


✅ 协程本质是"流程控制工具"

不是:

  • ❌ 真线程
  • ❌ 并发执行

而是:

👉 主动让出执行权


✅ 对比总结

方式 可读性 可维护性
回调 ❌ 差 ❌ 差
协程 ✅ 高 ✅ 高

📌 十一、本篇总结

🔥 协程让你用"同步写法"写出"异步逻辑"。


相关推荐
静心观复2 小时前
Lua 脚本是什么
开发语言·lua
智算菩萨2 小时前
【Pygame】第14章 摄像机系统与游戏视口控制技术
python·游戏·pygame
Swift社区2 小时前
为什么传统手游不适合鸿蒙游戏?
游戏·华为·harmonyos
星夜泊客2 小时前
《Lua 模块化核心:require 的地址传递与缓存机制》
缓存·lua
智算菩萨3 小时前
【Pygame】第18章 游戏性能优化与帧率控制
游戏·性能优化·pygame
ling__i3 小时前
接口测试常见问题
开发语言·lua
Swift社区3 小时前
鸿蒙游戏和小程序游戏的本质区别
游戏·小程序·harmonyos
RPGMZ3 小时前
RPGMZ游戏引擎 宠物战斗游戏基础功能实现
javascript·游戏·游戏引擎·宠物·rpgmz·rpgmakermz·宠物战斗系统
renhongxia14 小时前
基于角色的大型语言模型框架,用于从健康食品政策中提取结构化信息
人工智能·深度学习·游戏·microsoft·语言模型·自然语言处理·transformer