🧩 一、先说结论:协程解决什么问题?
在游戏开发中,你一定写过这种逻辑:
- 技能释放 → 等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
👉 会直接卡死游戏 ❌
🔥 十、高手用法(进阶理解)
✅ 协程本质是"流程控制工具"
不是:
- ❌ 真线程
- ❌ 并发执行
而是:
👉 主动让出执行权
✅ 对比总结
| 方式 | 可读性 | 可维护性 |
|---|---|---|
| 回调 | ❌ 差 | ❌ 差 |
| 协程 | ✅ 高 | ✅ 高 |
📌 十一、本篇总结
🔥 协程让你用"同步写法"写出"异步逻辑"。