如何在更改位置时调用函数?

How to invoke a function when changing position?

每当 position2D 节点的位置发生变化时,我都会尝试调用一个函数

我试图覆盖 docs 中给出的 setter,如下所示:

extends Position2D
tool

func set_position(value):
    print("changed position ",value)
    self.position=value;

我在这里错过了什么?有没有办法实现我正在尝试的目标?

方法set_position不是虚拟的。你没有覆盖它。充其量你是在隐藏它。

如果您想遵循该方法,请使用 _set 拦截 属性(请注意文档中提到 _set 是虚拟的)。思路就是我们要尝试设置position,设置了就想做什么就做什么,然后让它正常继续

func _set(property:String, value) -> bool:
    if property == "position":
        print("changed position ",value)

    return false

而且您应该会看到,当您在检查面板中修改 position 时,您会收到消息。


我怀疑这对你来说还不够。特别是上述解决方案无法检测到 position 何时更改,因为您在编辑器中拖动了 Position2D

这是因为当您在编辑器中移动 Position2D 时,Godot 没有设置 position 属性。相反,它是(在深入研究源代码之后)调用未记录的方法 _edit_set_position...您也可以从 GDScript 调用它!无论如何,关键是我们不能拦截它(我们不能覆盖它。是的,我试过了)。


相反,我们将使用 _notification。我们正在寻找 NOTIFICATION_TRANSFORM_CHANGED,但要获得该通知,我们需要使用 set_notify_transform 启用它。代码如下所示:

tool
extends Position2D

func _enter_tree() -> void:
    set_notify_transform(true)

func _notification(what: int) -> void:
    if what == NOTIFICATION_TRANSFORM_CHANGED:
        print("changed position", position)

通过这种方法,您还可以在用户通过四处拖动或使用键盘方向键在编辑器中移动 Position2D 时做出反应。 Godot 在哪些情况下使用 _edit_set_position。或者我们无法用初始方法拦截的任何其他方法。

如果 Node2D 每次移动都需要做一些事情,但它并不经常移动,则可以使用这种方法。

顺便说一句,这也适用于 3D。