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

任何将自身限制为字母字符(ato zAto Z)、数字(0to 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.1458.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.

注释

从 一个#到行尾的任何内容都将被忽略并被视为注释。

内置类型

内置类型是栈分配的。它们作为值传递。这意味着将在每个分配上或在将它们作为参数传递给函数时创建一个副本。唯一的例外是Arrays 和Dictionaries,它们是通过引用传递的,因此它们是共享的。(诸如此类的池化数组PoolByteArray仍作为值传递。)

基本的内置类型

GDScript 中的变量可以分配给多个内置类型。

null

null 是一个空数据类型,不包含任何信息,并且不能分配任何其他值。

bool

“boolean”的缩写,它只能包含truefalse

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

包含xy字段的2D 矢量类型。也可以作为数组访问。

Rect2

包含两个向量字段的 2D 矩形类型:positionsize。还包含一个end字段,即.position + size

Vector3

包含x,yz字段的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,yz),也可以作为 3D 向量数组访问。

Transform

3D 变换包含一个 Basis 字段basis和一个 Vector3 字段 origin

引擎内置类型

Color

颜色数据类型包含rgb,和a领域。它也可以作为hs和访问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 数组在内存中线性分配以提高速度。然而,大型数组(超过数万个元素)可能会导致内存碎片。如果这是一个问题,则可以使用特殊类型的阵列。这些只接受单一数据类型。它们避免内存碎片并使用更少的内存,但它们是原子的,并且往往比通用数组运行得慢。因此,仅建议将它们用于大型数据集:

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 NestedClassclass 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