Godot 和 GDScript 可以在变量中存储函数吗?

问题描述 投票:0回答:2

我对 GDScript 语言 的部分 Godot 文档感到困惑。大约在页面的中间,在“引用函数”部分,它说你不能将函数存储在变量中,然后似乎立即自相矛盾。

Godot 函数可以存储在变量中吗?

参考函数

与 Python 相反,函数在 GDScript 中不是第一类对象。 这意味着它们不能存储在变量中、作为参数传递给另一个函数或从其他函数返回。这是出于性能原因。

要在运行时按名称引用函数,(例如,将其存储在变量中,或将其作为参数传递给另一个函数)必须使用 call 或 funcref 帮助器:

function scripting godot gdscript
2个回答
25
投票

(最新)Godot v4.0+ 更新

Godot v4.0 添加了由

Callable
对象支持的一流函数和 lambda。

阅读过去的发布博客以获取更多信息。

现在,您可以按名称传递函数:

func callback(p_arg: String) -> void:
    print("Argument: ", p_arg)

func accept(p_callback) -> void:
    p_callback.call("accepted")

func _ready() -> void:
    accept(callback) # Prints "Argument: accepted"

并定义 lambda/闭包:

var lambda = func a_debug_label(p_arg: String) -> void:
    print("Argument: ", p_arg)
accept(lambda) # Prints: "Argument: accepted"

accept(func(p_arg): print(p_arg)) # Prints: "accepted"

Callables
替换 funcrefs:

var callable = Callable(my_obj, "some_func_name")
callable.call()

请注意,可调用对象是包装目标对象和函数名称的对象。可调用本身不是函数。您必须致电

some_callable.call()
。最后,lambda 的名称不可访问。它仅用于调试目的。


GDScript 函数不像 Python 中那样是对象。因此,您不能直接引用函数。

但是,您可以使用其关联的实例按名称间接引用它们。

例如具有以下功能:

func hello():
    print('Hello')

您可以通过名称调用实例上的函数:

call('hello') # prints 'Hello'

您可以使用

funcref()
存储实例和函数名称:

var ref = funcref(hello_object_instance, 'hello')
ref.call_func() # prints 'Hello'
takes_func_ref_to_call_later(ref) # later, prints 'Hello'

FuncRef.call_func()
Object.call()
做同样的事情,只是将其包装在一个对象中。

因此,如

Object.connect()
和朋友所示,回调函数的常见模式是:

func deferred_finish(param1, param2, callback_obj, callback_func):
    # ... do something
    callback_ref = funcref(callback_obj, callback_func)
func _process(delta):
    if _finished:
        callback_ref.call_func()
func _enter_tree():
    deferred_finish('hello', 'world', self, 'finished_callback')

我希望这有帮助。如果您需要任何说明,请告诉我。


5
投票

据我所知,它在 3.x 中不可用,但它是 Godot 4.0 中的一个功能,请参阅有关 引用函数 的文档(以及以下有关 lambda 的部分

基本上你可以使用声明变量

var f = func foo(x):
    <function body>

然后

f.call(x)
调用存储在该变量中的函数。

© www.soinside.com 2019 - 2024. All rights reserved.