“我正在参加掘金社区游戏创意投稿大赛个人赛,详情请看:游戏创意投稿大赛”
原文:Understanding tree order :: Godot Recipes (kidscancode.org)
作者:# Chris Bradfield
问题
理解 Godot 以何种顺序处理场景树
解决方法
Godot 文档和教程中经常提到 “Tree Order” 。 但是初学者并不容易明白这是什么意思。一般来说,树处理节点的方式都是自顶向下的。先从根开始,然后处理子树也就是各个分支。
“Tree Order” 会给 Godot 的初学者造成很大的疑惑。在本文中,我们将解释事情发生的顺序。
这是一个简单的示例
在每个节点,我们有如下的脚本
extends Node
func _init():
# 注意:节点在这里还没有名字
print("TestRoot init")
func _enter_tree():
print(name + " enter tree")
func _ready():
print(name + " ready")
# 保证我们只打印一次
var test = true
func _process(delta):
if test:
print(name + " process")
test = false
在我们关注结果之前,让我们回顾一下这些回调函数都代表什么。
-
_init()在对象首次被创建时被调用。 它储存在内存中。 -
_enter_tree()在节点第一次进入树时调用。比如说实例化时或者使用add_child()时。 -
_ready()在节点和它的孩子都被添加到了树中,并且就绪时被调用。 -
_process()在树的每个节点上每一帧中被调用,一个典型的情况是每秒 60 帧。
如果我们在一个节点上运行,我们猜测运行的顺序如下:
TestRoot init
TestRoot enter tree
TestRoot ready
TestRoot process
一旦将子节点添加进去,它将会变得更复杂,而且可能需要我们解释一下原因。
TestRoot init
TestChild1 init
TestChild3 init
TestChild2 init
TestRoot enter tree
TestChild1 enter tree
TestChild3 enter tree
TestChild2 enter tree
TestChild3 ready
TestChild1 ready
TestChild2 ready
TestRoot ready
TestRoot process
TestChild1 process
TestChild3 process
TestChild2 process
正如我们所看到的,所有的节点在“Tree Order”中自顶向下地打印了它们的信息(除了_ready()回调)。
文档中的相关说明 Node reference:
当节点 "就绪 "时被调用。子节点的
_ready()回调会首先被触发,而父节点会在之后收到就绪通知。
这是值得在设计节点结构时记忆的规则:
父节点应该管理子节点,而不是反过来。
这意味着父节点的代码都必须能够访问子节点的数据。因此,必须以反向的 Tree Order 处理 _ready()回调。
尝试在 _ready() 函数中访问其他节点时务必记住这一点。如果需要在树上访问父节点甚至是祖先节点,很有可能我们应该在父节点中运行相关代码而不是子节点。