本篇主要记录godot获取节点的方法或技巧。
NodePath
NodePath 在将一个节点作为参数导出时非常有用,它会减少此脚本与场景中其他节点的耦合性,保证你构建一个“可以单独运行的场景”。NodePath的表达方式类似一个文件路径,这与GoDot的节点设计哲学十分相符,你可以很简单的通过路径表达方式来确定一个节点。在我列出这些表示方法之前,请注意这些路径的起始为止为脚本所依附的那个节点。
为了更加清晰的表述,现在我设定一个节点结构。如图所示:
当前脚本挂载在Bullet上
NodePath 表示/语法
使用 @"xxx/xxx/xxx" 可以获得一个NodePath变量,除了导出节点时,你通常不会直接使用这个类型,想要获取一个节点时,一般地,可以使用 Node get_node(path: NodePath) const
方法:
# 将会输出 Bullet
print(get_node(@".").name)
# 将会输出 Bullet
print(get_node(".").name)
在上面的代码中,第二行中的 @"."
将返回一个 NodePath
,get_node
返回指定的节点,print
输出其名称。值得注意的是,由于NodePath可以通过字符串直接构造,在第4行中,字符串通过隐式转换构造为 NodePath
,从而也能够正确的调用get_node
。
我们可以在官方文档中,找到一个比较全面的NdePath
的各种写法:
# 没有路径前缀表示此路径是相对于当前节点的 @"A" #子节点A @"A/B" # A的子节点B @"." # 当前节点 @".." # 父节点 @"../C" # 兄弟节点C # 携带前缀路径表示场景树的绝对路径 @"/root" # 等同于 get_tree().get_root() @"/root/Main" # 主场景——"Main"(假设主场景的名字为Main) @"/root/MyAutoload" # 自动加载脚本——MyAutoload(如果有)
当然,为了更加快捷,建议使用GoDot提供的语法糖,$
:
print($".".name) # 与print(get_node(".").name) 一致
print($"Sprite".name) # 与print(get_node("Sprite").name) 一致
进一步地,有更加方便的写法来获取子节点:
print($Sprite.name)
export
对于一个场景来说,我们应尽力降低与其他节点的依赖,在脚本中直接指定其他节点将会造成两个节点的高耦合,使用export可以将NodePath进行导出,从而解决强依赖问题。
例如,子弹需要记录子弹的发射者,用于之后在击中时进行伤害判定,因此我们需要在脚本中获取子弹的发射者,如果将发射者硬编码,写死,将会导致子弹节点无法通用,这种子弹只能从你指定的节点上发射了。
值得庆幸的是,我们还有转机:
export(NodePath) var who_shoot_me
在脚本中导出NodePath,我们便可以在编辑器中选择一个节点
也可以在其他脚本中设置这个变量,这将会把我们从高耦合的设计中解救出来,帮助你完成更加健康,灵活的框架。