语句和控制流
语句是标准的,可以是赋值、函数调用、控制流结构等(见下文)。;
作为语句分隔符是完全可选的。
if/else/elif
简单的条件,通过创建if
/ else
/elif
语法。条件周围的括号是允许的,但不是必需的。鉴于基于制表符的缩进的性质,elif
可以用来代替 else
/if
来保持一定程度的缩进。
if [expression]: statement(s) elif [expression]: statement(s) else: statement(s)
短语句可以与条件写在同一行:
if 1 + 1 == 2: return 2 + 2 else: var x = 3 + 3 return x
有时,您可能希望根据布尔表达式分配不同的初始值。在这种情况下,三元 if 表达式就派上用场了:
var x = [value] if [expression] else [value] y += 3 if y < 10 else -1
While
使用while
语法创建简单循环。循环可以使用break
或继续使用continue
:
while [expression]:
statement(s)
For
要遍历一个范围,例如数组或表,请使用for循环。迭代数组时,当前数组元素存储在循环变量中。迭代字典时,键存储在循环变量中。
for x in [5, 7, 11]:
statement # Loop iterates 3 times with 'x' as 5, then 7 and finally 11.
var dict = {"a": 0, "b": 1, "c": 2}
for i in dict:
print(dict[i]) # Prints 0, then 1, then 2.
for i in range(3):
statement # Similar to [0, 1, 2] but does not allocate an array.
for i in range(1, 3):
statement # Similar to [1, 2] but does not allocate an array.
for i in range(2, 8, 2):
statement # Similar to [2, 4, 6] but does not allocate an array.
for c in "Hello":
print(c) # Iterate through all characters in a String, print every letter on new line.
for i in 3:
statement # Similar to range(3)
for i in 2.2:
statement # Similar to range(ceil(2.2))
Match(Switch)
一个match
语句用于程序的分支执行。它相当于switch
许多其他语言中的语句,但提供了一些附加功能。
基本语法:
match [expression]:
[pattern](s):
[block]
[pattern](s):
[block]
[pattern](s):
[block]
熟悉 switch 语句的人的速成课程:
- 替换
switch
为match
。 - 删除
case
。 - 删除任何
break
s。如果您不想在break
默认情况下使用,您可以使用continue
for fallthrough。 - 更改
default
为单个下划线。
控制流程:
图案从上到下匹配。如果模式匹配,将执行第一个相应的块。之后,在match
语句下方继续执行。您可以使用continue
停止当前块中的执行并检查其下方模式中的其他匹配项。
Class
默认情况下,所有脚本文件都是未命名的类。在这种情况下,您只能使用文件的路径(使用相对路径或绝对路径)来引用它们。例如,如果您命名一个脚本文件character.gd
:
# Inherit from 'Character.gd'.
extends "res://path/to/character.gd"
# Load character.gd and create a new node instance from it.
var Character = load("res://path/to/character.gd")
var character_node = Character.new()
您可以为您的类命名,以便在 Godot 的编辑器中将其注册为新类型。为此,您使用class_name
关键字。您可以添加一个可选的逗号,后跟图像的路径,以将其用作图标。然后,您的类将在编辑器中显示其新图标:
# Item.gd
extends Node
class_name Item, "res://interface/icons/item.png"
警告
如果脚本位于res://addons/
目录中,并且脚本是启用的编辑器插件的一部分,class_name
则只会导致节点显示在“创建新节点”对话框中。有关 更多信息,请参阅制作插件。
这是一个类文件示例:
# Saved as a file named 'character.gd'.
class_name Character
var health = 5
func print_health():
print(health)
func print_this_script_three_times():
print(get_script())
print(ResourceLoader.load("res://character.gd"))
print(Character)
笔记
Godot 的类语法很紧凑:它只能包含成员变量或函数。您可以使用静态函数,但不能使用静态成员变量。同样,引擎每次创建实例时都会初始化变量,这包括数组和字典。这是本着线程安全的精神,因为脚本可以在用户不知情的情况下在单独的线程中初始化。
继承
一个类(存储为文件)可以继承自:
- 一个全局类。
- 另一个类文件。
- 另一个类文件中的内部类。
不允许多重继承。
继承使用extends
关键字:
# Inherit/extend a globally available class.
extends SomeClass
# Inherit/extend a named class file.
extends "somefile.gd"
# Inherit/extend an inner class in another file.
extends "somefile.gd".SomeInnerClass
要检查给定实例是否继承自给定类,is
可以使用关键字:
# Cache the enemy class.
const Enemy = preload("enemy.gd")
# [...]
# Use 'is' to check inheritance.
if entity is Enemy:
entity.apply_damage()
要调用父类中的函数(即extend
当前类中的一个),.
请在函数名前加上:
.base_func(args)
这特别有用,因为扩展类中的函数替换了父类中同名的函数。如果您仍想调用它们,可以使用前缀.
(如super
其他语言中的关键字):
func some_func(x):
.some_func(x) # Calls the same function on the parent class.
笔记
在所有父类中自动调用_init
诸如 、_enter_tree
、_exit_tree
、_process
、_physics_process
、 等大多数通知的 默认函数 。重载它们时无需显式调用它们。
类构造函数
在类实例化时调用的类构造函数名为_init
。如前所述,继承类时会自动调用父类的构造函数。所以,通常不需要._init()
显式调用。
与常规函数的调用不同,就像上面的例子中的 .some_func
,如果继承类的构造函数接受参数,它们会像这样传递:
func _init(args).(parent_args):
pass
通过示例可以更好地解释这一点。考虑这个场景:
# State.gd (inherited class) 父类 var entity = null var message = null func _init(e=null): entity = e func enter(m): message = m # Idle.gd (inheriting class) 子类 extends "State.gd" func _init(e=null, m=null).(e): # Do something with 'e'. message = m
- 如果父类(
State.gd
) 定义了一个接受参数e的构造函数_init
,那么子类 (Idle.gd
) 也必须 定义_init
,并将适当的参数传递给_init
。 Idle.gd
可以有与父类不同数量的参数- 在上面的示例中,
e
传递给State.gd
构造函数与e
传递给Idle.gd
. - 如果
Idle.gd
的_init
构造函数接受 0 个参数,它仍然需要将一些值传递给State.gd
父类,即使它什么都不做。这让我们认识到,您也可以在基本构造函数中传递文字,而不仅仅是变量。例如。:
# Idle.gd func _init().(5): pass