【UnLua】UnLua Latent 实现机制

【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,协程的好处就是和写正常的同步代码看起来是一样的

蓝图

【UnLua】UnLua Latent 实现机制_第1张图片

Lua

【UnLua】UnLua Latent 实现机制_第2张图片

蓝图 Latent 只能由 C++ 实现独立节点,蓝图在 EventGraph 顶层调用,不可嵌套
【UnLua】UnLua Latent 实现机制_第3张图片

可以用宏包装,但是并不改变这个机制

在这里插入图片描述

正文

以 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 起了一个协程

【UnLua】UnLua Latent 实现机制_第4张图片

读 meta,判定 latent

【UnLua】UnLua Latent 实现机制_第5张图片

Latent 函数的 C Wrapper,注意返回时用的是 lua_yield

【UnLua】UnLua Latent 实现机制_第6张图片

CallUE>Precall,Latent 函数有一个 FLatentActionInfo 参数,在这里构造

【UnLua】UnLua Latent 实现机制_第7张图片

反射绑定 LuaManager::OnLatentActionCompeleted 作为回调,还有创建出来的协程ID ThreadRef
在这里插入图片描述

终于到 C++ 的 Delay

【UnLua】UnLua Latent 实现机制_第8张图片

FLatentActionInfo 的状态,很清楚了
【UnLua】UnLua Latent 实现机制_第9张图片

Delay回调,只传了一个 ThreadID

在这里插入图片描述

找到 Thread,resume 回到 Delay 后的 Lua 代码
【UnLua】UnLua Latent 实现机制_第10张图片

你可能感兴趣的:(游戏编程扯淡精粹,1024程序员节)