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

👉 会直接卡死游戏 ❌


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


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

不是:

  • ❌ 真线程
  • ❌ 并发执行

而是:

👉 主动让出执行权


✅ 对比总结

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

📌 十一、本篇总结

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


相关推荐
liulilittle6 小时前
麻将结算全链路语义(SETTLE_SEMANTICS)
ai·自动化·llm·mock·lua·测试
SmalBox8 小时前
02-05-原理篇-资源加载与缓存机制
unity3d·游戏开发
liulilittle8 小时前
麻将服务器崩溃补偿与异常处理语义(CRASH_SEMANTICS)
ai·自动化·llm·mock·lua·测试·tools
liulilittle8 小时前
麻将 UI 层可观察行为(UI_BEHAVIOR)
ai·自动化·llm·mock·lua·测试·tools
liulilittle11 小时前
C++ 引擎接口到 mock 的映射(INTERFACE_MAP)
ai·自动化·llm·mock·lua·测试·tools
林川~0119 小时前
Unity 万能物理检测工具:射线检测 / 范围检测 / 层级过滤 / 编辑器可视化(可直接拿去用)
游戏·unity·c#·射线检测·通用工具
SmalBox21 小时前
02-04-原理篇-资源组织与依赖分析
unity3d·游戏开发
青穗CherishTang1 天前
关于Retrofit+Kotlin Flow协程网络请求的封装(全新版)
网络请求·协程·retrofit·flow
Huanzhi_Lin1 天前
从0搭建ECS:跨品类评估
架构·游戏开发·ecs·ecs跨品类评估
甲维斯1 天前
《钢铁洪流》开发笔记:AI策略升级!
人工智能·游戏开发