【UnLua】UnLua Latent 实现机制
跟了一下 UnLua Latent,其实就是 Unity 协程,下面也会用【协程】这个词指代
协程是一个比较简单的点,主要是玩法会用到
小结
本质原理是 Lua 支持和 C 进行 yield 和 resume 操作
实现上,Lua 调用 Delay 时 yield 给 C,C 把当前的 Lua Thread 管理起来,并分配一个 ID,存到 UE
的 FLatentActionInfo,等 UE 完成异步任务后,回调给 LuaManager,C yield 给 Lua,Lua resume
蓝图的 Latent 和 Lua 协程都是 VM 实现的,目前看来蓝图完败,不支持嵌套,只能简单 Demo 用
蓝图 Latent
Lantent 最简单的 case 就是 Delay,协程的好处就是和写正常的同步代码看起来是一样的
蓝图
Lua
蓝图 Latent 只能由 C++ 实现独立节点,蓝图在 EventGraph 顶层调用,不可嵌套
可以用宏包装,但是并不改变这个机制
正文
以 Tutorial 里的 case 为例
local function run(self, name)
Screen.Print(string.format("协程%s:启动", name))
for i = 1, 5 do
UE.UKismetSystemLibrary.Delay(self, 1)
Screen.Print(string.format("协程%s:%d", name, i))
end
Screen.Print(string.format("协程%s:结束", name))
end
function M:ReceiveBeginPlay()
local msg = [[
—— 本示例来自 "Content/Script/Tutorials.07_CallLatentFunction.lua"
]]
Screen.Print(msg)
coroutine.resume(coroutine.create(run), self, "A")
coroutine.resume(coroutine.create(run), self, "B")
end
输出
Construct
协程A:启动
协程B:启动
协程A:1
协程B:1
协程B:2
协程A:2
协程A:3
协程B:3
协程B:4
协程A:4
协程A:5
协程A:结束
协程B:5
协程B:结束
Latent meta 标记
注意,lua 这边 corutine.resume 起了一个协程
读 meta,判定 latent
Latent 函数的 C Wrapper,注意返回时用的是 lua_yield
CallUE>Precall,Latent 函数有一个 FLatentActionInfo 参数,在这里构造
反射绑定 LuaManager::OnLatentActionCompeleted
作为回调,还有创建出来的协程ID ThreadRef
终于到 C++ 的 Delay
了
FLatentActionInfo
的状态,很清楚了
Delay
回调,只传了一个 ThreadID
找到 Thread,resume 回到 Delay 后的 Lua 代码