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

👉 会直接卡死游戏 ❌


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


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

不是:

  • ❌ 真线程
  • ❌ 并发执行

而是:

👉 主动让出执行权


✅ 对比总结

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

📌 十一、本篇总结

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


相关推荐
JoyCong19984 小时前
ToDesk游戏操控功能:用手柄与虚拟键盘畅玩3A大作
安全·游戏·计算机外设·电脑·远程工作·远程操作
wgc2k5 小时前
Oops Framework-4-Oops Framework入口类Root.ts
游戏·cocos2d
混迹中的咸鱼5 小时前
游戏开发核心架构指南
c++·游戏·架构
xingpanvip1 天前
星盘接口开发文档:马盘次限盘接口指南
android·开发语言·python·php·lua
avi91111 天前
Unity 商业插件之(五)课外2 - Zenject的一些小Tips(学习备忘)
unity·游戏开发·团结引擎
aaaffaewrerewrwer1 天前
一个更流畅、更纯粹的在线 2048 游戏(浏览器即开 / 无需下载)
游戏·2048
selt7911 天前
Redisson 源码深度分析
java·c++·redis·lua
FFZero11 天前
[mpv脚本系统] (三) C 函数如何注册成 Lua 模块
c++·音视频·lua
SmalBox1 天前
【节点】[TriangleWave节点]原理解析与实际应用
unity3d·游戏开发·图形学
Kingairy1 天前
LUA环境搭建
开发语言·lua