Godot里的信息流动

父节点可以访问子节点的属性和方法。但是子节点无权访问同级节点和父节点的任何信息。所以若想沟通有无,则需要使用信号,访问场景树或自动加载节点(AutoLoad)等手段。

信号

通常是各种外部输入信号,也可以是自己定义的信号。
当采用默认的外部输入信号时,名称和函数头可以自动建立,连接函数也是写在内部。在代码里看不到信号申明,也看不到连接函数,只能看到在父节点或同级节点里的信号方法(接到信号要做的事,自己编写)以及在编辑器里的信号提示。
反之,若采用自己定义的信号,则需要申明信号,发射信号,连接信号,编写信号方法。
具体使用方法:

  • 子节点里添加信号(申明信号名称)或自动申明自带信号,以及何时发射信号(emit)或通过外部输入自动发射信号;
  • 父节点/同级节点里添加连接函数(connect)或通过编辑器连接信号,以及接受信号后要做的信号方法;父节点/同级节点里添加yield(object , "信号名") 可以使信号发挥作用,不需要连接方法。

附注: 有时候信号还可以单纯用作触发,此时可以将要连接的方法函数写在节点本身,这样实际没有信息流动。当然这样做,要么就是完全不需要其他信息就可以实现的功能,要么就是需要访问场景树,获得信息来完成功能,个人认为,访问场景树的话,效率低下,看似将该节点去耦合了,但实际上并没有,访问场景树时就通过固定的语句将其固定死了。所以,我认为此举得不偿失。

访问场景树

get_tree().current_scene 可以得到当前场景树,再通过访问场景树即可访问/修改父(同级)节点的属性和方法。

该方法快速方便,但是加重了各个节点的耦合程度,信号是松散的结合,但是本方法几乎使节点无法复用。(只适合在一个场景中的节点,该节点无法作为一个通用场景模板,而使用信号方法的节点可以作为通用场景模板,因为没有使用get_tree语句,而且,信号还可以配合 yield 语句工作,非常简洁完成信息沟通)
根据一般定义,子节点是无法访问父节点的属性方法的,但此方法可以使得子节点访问到父节点信息,这是不安全的。对代码整体整洁性产生影响,不利于阅读。

AutoLoad(单例/全局变量)

在项目设置里可以专门将某节点化为AutoLoad,此时该节点会在任何场景树中加载,且任何节点都可以调用其属性和方法。
自动加载有两个好处,第一是方便信息流动,任意节点都可访问该节点,第二是当切换场景时,该节点仍挂载在场景树上,也就是说方便转场保存用户数据。

setget

setget实现对本节点属性的监控。若是外部节点(父节点)修改了本节点的属性,就可以触发setget函数,所以setget并没有超出默认的信息流动规则,就算没有这个东西,也能找到办法实现相同的功能。它只是一个方便的自动化工具。
当此节点属性值变化就会自动触发,若希望本节点修改本身的属性也要监控,则在修改时申明为self.属性名即可。

最后修改:2020 年 03 月 17 日
如果觉得我的文章对你有用,请随意赞赏