Tencent / UnLua

A feature-rich, easy-learning and highly optimized Lua scripting plugin for UE.
Other
2.24k stars 614 forks source link

如何绕过Delegate Signature检查进行绑定 #685

Open cymhellfire opened 10 months ago

cymhellfire commented 10 months ago

在旧版本Unlua中使用辅助脚本可以实现:不与UObject实例绑定的脚本上的函数可以绑定到Dynamic Multicast Delegate上。如下

local DelegateHelper = UnrealClass()

function DelegateHelper:OnReset()
    -- Unbind the delegate when reset
    self:UnbindDelegate()
end

---Bind a callback function to specified delegate.
---@param InDelegate MulticastDelegate Native delegate pointer.
---@param InListener any Listener instance that holds the callback function.
---@param InCallback function Callback function to trigger.
function DelegateHelper:BindDelegate(InDelegate, InListener, InCallback)
    if not InDelegate then
        return--[[  ]]
    end
    InDelegate:Add(self, self.OnNativeDelegateTriggered)

    self._NativeDelegate = InDelegate
    self._Listener = InListener
    self._Callback = InCallback
end

---Unbind the callback from native delegate.
function DelegateHelper:UnbindDelegate()
    if not self._NativeDelegate then
        return
    end

    self._NativeDelegate:Remove(self, self.OnNativeDelegateTriggered)
end

---Callback function that response to native delegate.
---And pass the parameters to lua callback.
function DelegateHelper:OnNativeDelegateTriggered(...)
    if self._Listener and self._Callback then
        self._Callback(self._Listener, ...)
    end
end

return DelegateHelper

只需确保上述脚本绑定了UObject,即可使用Lua脚本将回调参数透传给需要的脚本。 但是升级到最新版本Unlua后,增加了CheckSignatureCompatible()方法进行了校验,导致上述脚本无法进行绑定。

请问有其他方式实现类似的功能吗?

cymhellfire commented 10 months ago

这边自己排查了一下,发现项目中对上述Helper实例进行了复用操作。导致复用的实例在进行第二次绑定时,会触发Signature比较。这边移除了复用逻辑后,Helper类注册的回调就可以正常使用了。

不确定底层的具体逻辑,感觉像是在绑定Lua回调时,Unlua会维护一个Map用于记录绑定过的Delegate信息。想知道一直使用上述代码注册回调,是否会有潜在的性能问题。