GDScript是一种用于创建内容的高级动态类型编程语言。它使用类似于Python的语法 (块是基于缩进的并且许多关键字是相似的)。其目标是针对Godot Engine进行优化并与之紧密集成,从而为内容创建和集成提供极大的灵活性。
有些人可以通过查看语法来更好地学习,所以这里有一个 GDScript 外观的简单示例。
# A file is a class! # Inheritance extends BaseClass # (optional) class definition with a custom icon class_name MyClass, "res://path/to/optional/icon.svg" # Member variables var a = 5 var s = "Hello" var arr = [1, 2, 3] var dict = {"key": "value", 2: 3} var typed_var: int var inferred_type := "String" # Constants const ANSWER = 42 const THE_NAME = "Charly" # Enums enum {UNIT_NEUTRAL, UNIT_ENEMY, UNIT_ALLY} enum Named {THING_1, THING_2, ANOTHER_THING = -1} # Built-in vector types var v2 = Vector2(1, 2) var v3 = Vector3(1, 2, 3) # Function func some_function(param1, param2): var local_var = 5 if param1 < local_var: print(param1) elif param2 > 5: print(param2) else: print("Fail!") for i in range(20): print(i) while param2 != 0: param2 -= 1 var local_var2 = param1 + 3 return local_var2 # Functions override functions with the same name on the base/parent class. # If you still want to call them, use '.' (like 'super' in other languages). func something(p1, p2): .something(p1, p2) # Inner class class Something: var a = 10 # Constructor func _init(): print("Constructed!") var lv = Something.new() print(lv.a)
如果您以前有使用静态类型语言(如 C、C++ 或 C#)但从未使用过动态类型语言的经验,建议您阅读本教程:GDScript:动态语言简介。
语言
下面对 GDScript 进行概述。如果要查找详细信息,例如哪些方法可用于数组或其他对象。应该在链接的类描述中查找。
Identifiers
任何将自身限制为字母字符(a
to z
和A
to Z
)、数字(0
to 9
)并_
有资格作为标识符的字符串。此外,标识符不得以数字开头。标识符区分大小写(foo
不同于FOO
)。
关键词
以下是该语言支持的关键字列表。由于关键字是保留字(标记),因此不能用作标识符。
Keyword | Description |
---|---|
if | See if/else/elif. |
elif | See if/else/elif. |
else | See if/else/elif. |
for | See for. |
while | See while. |
match | See match. |
break | Exits the execution of the current for or while loop. |
continue | Immediately skips to the next iteration of the for or while loop. |
pass | Used where a statement is required syntactically but execution of code is undesired, e.g. in empty functions. |
return | Returns a value from a function. |
class | Defines an inner class. |
class_name | Defines a class name and optional icon for your script. |
extends | Defines what class to extend with the current class. |
is | Tests whether a variable extends a given class, or is of a given built-in type. |
as | Cast the value to a given type if possible. |
self | Refers to current class instance. |
tool | Executes the script in the editor. |
signal | Defines a signal. |
func | Defines a function. |
static | Defines a static function. Static member variables are not allowed. |
const | Defines a constant. |
enum | Defines an enum. |
var | Defines a variable. |
onready | Initializes a variable once the Node the script is attached to and its children are part of the scene tree. |
export | Saves a variable along with the resource it’s attached to and makes it visible and modifiable in the editor. |
setget | Defines setter and getter functions for a variable. |
breakpoint | Editor helper for debugger breakpoints. |
preload | Preloads a class or variable. See Classes as resources. |
yield | Coroutine support. See Coroutines with yield. |
assert | Asserts a condition, logs error on failure. Ignored in non-debug builds. See Assert keyword. |
remote | Networking RPC annotation. See high-level multiplayer docs. |
master | Networking RPC annotation. See high-level multiplayer docs. |
puppet | Networking RPC annotation. See high-level multiplayer docs. |
remotesync | Networking RPC annotation. See high-level multiplayer docs. |
mastersync | Networking RPC annotation. See high-level multiplayer docs. |
puppetsync | Networking RPC annotation. See high-level multiplayer docs. |
PI | PI constant. |
TAU | TAU constant. |
INF | Infinity constant. Used for comparisons. |
NAN | NAN (not a number) constant. Used for comparisons. |
运算符
以下是支持的运算符列表及其优先级。
Operator | Description |
x[index] |
Subscription (highest priority) |
x.attribute |
Attribute reference |
foo() |
Function call |
is |
Instance type checker |
~ |
Bitwise NOT |
-x |
Negative / Unary negation |
* / % |
Multiplication / Division / Remainder
These operators have the same behavior as C++. Integer division is truncated rather than returning a fractional number, and the % operator is only available for ints (“fmod” for floats) |
+ |
Addition / Concatenation of arrays |
- |
Subtraction |
<< >> |
Bit shifting |
& |
Bitwise AND |
^ |
Bitwise XOR |
| |
Bitwise OR |
< > == != >= <= |
Comparisons |
in |
Content test |
! not |
Boolean NOT |
and && |
Boolean AND |
or || |
Boolean OR |
if x else |
Ternary if/else |
as |
Type casting |
= += -= *= /= %= &= |= |
Assignment (lowest priority) |
Literals
Literal | Type |
45 |
Base 10 integer |
0x8f51 |
Base 16 (hexadecimal) integer |
0b101010 |
Base 2 (binary) integer |
3.14 , 58.1e-10 |
Floating-point number (real) |
"Hello" , "Hi" |
Strings |
"""Hello""" |
Multiline string |
@"Node/Label" |
NodePath or StringName |
$NodePath |
Shorthand for get_node("NodePath") |
整数和浮点数可以用 分隔它们的数字_
,使它们更具可读性。以下写数字的方法都是有效的:
12_345_678 # Equal to 12345678.
3.141_592_7 # Equal to 3.1415927.
0x8080_0000_ffff # Equal to 0x80800000ffff.
0b11_00_11_00 # Equal to 0b11001100.
注释
从 一个#
到行尾的任何内容都将被忽略并被视为注释。
内置类型
内置类型是栈分配的。它们作为值传递。这意味着将在每个分配上或在将它们作为参数传递给函数时创建一个副本。唯一的例外是Array
s 和Dictionaries
,它们是通过引用传递的,因此它们是共享的。(诸如此类的池化数组PoolByteArray
仍作为值传递。)
基本的内置类型
GDScript 中的变量可以分配给多个内置类型。
null
null
是一个空数据类型,不包含任何信息,并且不能分配任何其他值。
bool
“boolean”的缩写,它只能包含true
或false
。
int
“整数”的缩写,它存储整数(正数和负数)。它存储为 64 位值,相当于 C++ 中的“int64_t”。
float
使用浮点值存储实数,包括小数。它存储为 64 位值,相当于 C++ 中的“double”。注意:目前,Vector2、Vector3 和 PoolRealArray 等数据结构存储 32 位单精度“浮点”值。
String
Unicode 格式的字符序列。字符串可以包含以下转义序列:
Escape sequence | Expands to |
\n |
Newline (line feed) |
\t |
Horizontal tab character |
\r |
Carriage return |
\a |
Alert (beep/bell) |
\b |
Backspace |
\f |
Formfeed page break |
\v |
Vertical tab character |
\" |
Double quote |
\' |
Single quote |
\\ |
Backslash |
\uXXXX |
Unicode codepoint XXXX (hexadecimal, case-insensitive) |
GDScript 还支持GDScript 格式字符串。
向量内置类型
Vector2
包含x
和y
字段的2D 矢量类型。也可以作为数组访问。
Rect2
包含两个向量字段的 2D 矩形类型:position
和size
。还包含一个end
字段,即.position + size
Vector3
包含x
,y
和z
字段的3D 矢量类型。也可以将其作为数组进行访问。
Transform2D
用于 2D 变换的 3×2 矩阵。
Plane
归一化形式的3D平面类型,其中包含normal
矢量场和d
标量距离。
Quat
四元数是用于表示 3D 旋转的数据类型。它对于插入旋转很有用。
AABB
轴对齐边界框(或 3D 框)包含 2 个向量字段:position
和size
。还包含一个end
字段,即 .position + size
Basis
用于 3D 旋转和缩放的 3×3 矩阵。它包含 3 个向量场(x
,y
和z
),也可以作为 3D 向量数组访问。
Transform
3D 变换包含一个 Basis 字段basis
和一个 Vector3 字段 origin
。
引擎内置类型
Color
颜色数据类型包含r
,g
,b
,和a
领域。它也可以作为h
、s
和访问v
色相/饱和度/值。
NodePath
主要用于场景系统的节点的编译路径。它可以很容易地分配给一个字符串,或者从一个字符串中分配。
RID
资源 ID (RID)。服务器使用通用 RID 来引用不透明数据。
Object
任何非内置类型的基类。
容器内置类型
Array
任意对象类型的通用序列,包括其他数组或字典(见下文)。数组可以动态调整大小。数组从 index 开始索引0
。负指数从最后开始计数。
var arr = [] arr = [1, 2, 3] var b = arr[1] # This is 2. var c = arr[arr.size() - 1] # This is 3. var d = arr[-1] # Same as the previous line, but shorter. arr[0] = "Hi!" # Replacing value 1 with "Hi!". arr.append(4) # Array is now ["Hi!", 2, 3, 4].
GDScript 数组在内存中线性分配以提高速度。然而,大型数组(超过数万个元素)可能会导致内存碎片。如果这是一个问题,则可以使用特殊类型的阵列。这些只接受单一数据类型。它们避免内存碎片并使用更少的内存,但它们是原子的,并且往往比通用数组运行得慢。因此,仅建议将它们用于大型数据集:
- PoolByteArray:字节数组(0 到 255 之间的整数)。
- PoolIntArray:整数数组。
- PoolRealArray:一个浮点数数组。
- PoolStringArray:字符串数组。
- PoolVector2Array : Vector2对象的数组。
- PoolVector3Array : Vector3对象的数组。
- PoolColorArray : Color对象的数组。
Dictionary
关联容器,其中包含唯一键引用的值。
var d = {4: 5, "A key": "A value", 28: [1, 2, 3]} d["Hi!"] = 0 d = { 22: "value", "some_key": 2, "other_key": [2, 3, 4], "more_key": "Hello" }
还支持 Lua 风格的表语法。Lua 风格使用=
而:
不是使用引号来标记字符串键(使编写稍微少一些)。但是,以这种形式编写的密钥不能以数字开头(如任何 GDScript 标识符)。
var d = { test22 = "value", some_key = 2, other_key = [2, 3, 4], more_key = "Hello" }
要将键添加到现有字典,请像访问现有键一样访问它并分配给它:
var d = {} # Create an empty Dictionary. d.waiting = 14 # Add String "waiting" as a key and assign the value 14 to it. d[4] = "hello" # Add integer 4 as a key and assign the String "hello" as its value. d["Godot"] = 3.01 # Add String "Godot" as a key and assign the value 3.01 to it. var test = 4 # Prints "hello" by indexing the dictionary with a dynamic key. # This is not the same as `d.test`. The bracket syntax equivalent to # `d.test` is `d["test"]`. print(d[test])
括号语法可用于访问任何Object 的属性 ,而不仅仅是 Dictionaries。请记住,尝试索引不存在的属性时会导致脚本错误。为避免这种情况,请改用Object.get()和 Object.set()方法。
Data
变量
变量可以作为类成员或函数的局部变量存在。它们是用var
关键字创建的,并且可以选择在初始化时分配一个值。
var a # Data type is 'null' by default.
var b = 5
var c = 3.8
var d = b + c # Variables are always initialized in order.
变量可以选择具有类型说明。指定类型时,变量将被迫始终具有相同的类型,并且尝试分配不兼容的值将引发错误。
类型在变量声明中使用:
变量名后的(冒号)符号指定,后跟类型。
var my_vector2: Vector2
var my_node: Node = Sprite.new()
如果变量在声明中初始化,则可以推断类型,因此可以省略类型名称:
var my_vector2 := Vector2() # 'my_vector2' is of type 'Vector2'.
var my_node := Sprite.new() # 'my_node' is of type 'Sprite'.
只有在分配的值具有定义的类型时才可以进行类型推断,否则会引发错误。
有效类型是:
- 内置类型(Array、Vector2、int、String 等)。
- 引擎类(节点、资源、引用等)。
- 如果常量名称包含脚本资源(
MyScript
如果已声明),则为常量名称。const MyScript = preload("res://my_script.gd")
- 其他类在同一个脚本,尊重范围(
InnerClass.NestedClass
如果你声明里面的在同一范围内)。class NestedClass
class InnerClass
- 用
class_name
关键字声明的脚本类。
casting
分配给类型化变量的值必须具有兼容的类型。如果需要将值强制为某种类型,尤其是对象类型,则可以使用强制转换运算符as
。
如果值属于相同类型或转换类型的子类型,则对象类型之间的转换会产生相同的对象
var my_node2D: Node2D my_node2D = $Sprite as Node2D # Works since Sprite is a subtype of Node2D.
如果该值不是子类型,则转换操作将产生一个null
值。
var my_node2D: Node2D my_node2D = $Button as Node2D # Results in 'null' since a Button is not a subtype of Node2D.
对于内置类型,如果可能,它们将被强制转换,否则引擎将引发错误。
var my_int: int
my_int = "123" as int # The string can be converted to int.
my_int = Vector2() as int # A Vector2 can't be converted to int, this will cause an error
在与场景树交互时,转换对于拥有更好的类型安全变量也很有用:
# Will infer the variable to be of type Sprite.
var my_sprite := $Character as Sprite
# Will fail if $AnimPlayer is not an AnimationPlayer, even if it has the method 'play()'.
($AnimPlayer as AnimationPlayer).play("walk")
常数
常量是您在游戏运行时无法更改的值。它们的值必须在编译时知道。使用 const
关键字可以为常量值命名。在声明常量后尝试为其赋值会给您带来错误。
枚举
枚举基本上是常量的简写,如果您想将连续的整数分配给某个常量,它非常有用。
如果您将名称传递给枚举,它会将所有键放入该名称的常量字典中。
enum {TILE_BRICK, TILE_FLOOR, TILE_SPIKE, TILE_TELEPORT}
# Is the same as:
const TILE_BRICK = 0
const TILE_FLOOR = 1
const TILE_SPIKE = 2
const TILE_TELEPORT = 3
enum State {STATE_IDLE, STATE_JUMP = 5, STATE_SHOOT}
# Is the same as:
const State = {STATE_IDLE = 0, STATE_JUMP = 5, STATE_SHOOT = 6}
# Access values with State.STATE_IDLE, etc.
函数
函数总是属于一个类。变量查找的作用域优先级是:本地→类成员→全局。该self
变量始终可用,并提供用于访问类成员的选择,但并不总是需要(也应该不会被作为函数的第一个参数,不同的Python)。
func my_function(a, b):
print(a)
print(b)
return a + b # Return is optional; without it 'null' is returned.
一个函数可以在任何时候return
。默认返回值为null
。
函数还可以具有参数和返回值的类型规范。可以以与变量类似的方式添加参数类型
func my_function(a: int, b: String):
pass
如果函数参数具有默认值,则可以推断类型:
func my_function(int_arg := 42, String_arg := "string"):
pass
可以使用箭头标记 ( ->
)在参数列表后指定函数的返回类型:
func my_int_function() -> int:
return 0
具有返回类型的函数必须返回正确的值。将类型设置为void
意味着该函数不返回任何内容。void 函数可以使用return
关键字提前返回,但它们不能返回任何值。
void_function() -> void:
return # Can't return a value
非 void 函数必须始终返回一个值,因此如果您的代码具有分支语句(例如if
/else
构造),则所有可能的路径都必须有一个返回值。例如,如果您return
在if
块内部但不在块之后,则编辑器将引发错误,因为如果块未执行,则该函数将没有可返回的有效值。
函数引用
与 Python 不同,函数不是GDScript 中的一级对象。这意味着它们不能存储在变量中,不能作为参数传递给另一个函数或从其他函数返回。这是出于性能原因。
要在运行时按名称引用函数(例如,将其存储在变量中,或将其作为参数传递给另一个函数),必须使用call
或 funcref
助手:
# Call a function by name in one step.
my_node.call("my_function", args)
# Store a function reference.
var my_func = funcref(my_node, "my_function")
# Call stored function reference.
my_func.call_func(args)
静态函数
一个函数可以声明为静态的。当函数为静态时,它无法访问实例成员变量或self
. 这主要用于制作辅助函数库:
static func sum2(a, b):
return a + b