本文基于 Godot 4.5,重点介绍 GDScript 与 TypeScript 之间的语法差异。
GDScript 是一门支持渐进式静态类型的语言,可以将它理解为:
Python 风格语法 + 可选静态类型 + Godot API
1. 基础语法对照
| TypeScript | GDScript |
|---|---|
let value = 1 | var value = 1 |
const MAX = 10 | const MAX: int = 10 |
number | int / float |
string | String |
boolean | bool |
T[] | Array[T] |
Map<K, V> | Dictionary[K, V] |
null / undefined | null |
function | func |
switch | match |
condition ? a : b | a if condition else b |
async/Promise | await + Signal |
instanceof | is |
import | class_name / preload() |
GDScript 使用缩进表示代码块,不需要花括号和分号。
-> :
return
return %
2. 变量与常量
动态类型变量
= 10
=
使用 = 且不声明类型时,变量按动态类型处理,类似 TypeScript 中的 any。
显式静态类型
: = 10
: = 120.0
: =
: =
静态类型变量不能被赋予其他类型:
: = 10
# 编译错误
=
类型推导
使用 := 让编译器推导静态类型:
:= 10
:= 120.0
:=
:=
下面的代码会产生类型错误:
:= 10
# count 已被推导为 int
=
常量
: = 100
: =
:=
常量通常使用 UPPER_SNAKE_CASE 命名。
3. 基础类型
: = 10
: = 10.5
: =
: =
: =
: =
: = ^
: = &
TypeScript 的 number 在 GDScript 中分为:
int:整数float:浮点数
注意整数除法:
:= 5 / 2
:= 5.0 / 2
# 2
# 2.5
4. 字符串
字符串声明
:=
:=
多行字符串
:=
字符串格式化
GDScript 没有 JavaScript 模板字符串,通常使用 %:
:=
:= 100
:= %
常用格式:
| 格式 | 含义 |
|---|---|
%s | 字符串 |
%d | 整数 |
%f | 浮点数 |
%.2f | 保留两位小数 |
示例:
:= 12.3456
:= %
5. 数组
声明数组
: =
: =
添加和删除元素
: =
访问元素
: =
负数索引表示从数组末尾开始访问。
遍历数组
: =
获取索引:
数组复制
Array 是引用类型:
: =
:=
# [1, 2, 3, 4]
复制数组:
:=
深复制:
:=
6. Dictionary
Dictionary 类似 TypeScript 的 Map 或普通对象。
声明 Dictionary
: =
读取和修改
= 120
: =
判断键是否存在
安全读取
: =
遍历 Dictionary
: =
也可以分别获取键和值:
Dictionary 同样是引用类型,需要复制时使用:
:=
7. 运算符
算术运算符
:= 10 + 5
:= 10 - 5
:= 10 * 5
:= 10.0 / 5.0
:= 10 % 3
:= 2 ** 3
比较运算符
==
!=
>
>=
<
<=
GDScript 没有 TypeScript 中的 === 和 !==。
逻辑运算符
推荐使用:
and
or
not
也支持:
&&
||
!
三元表达式
TypeScript:
const result = condition ? "yes" : "no";
GDScript:
:=
成员判断
: =
Dictionary:
8. 条件语句
:= 85
>= 80:
GDScript 使用 elif,而不是 TypeScript 的 else if。
9. Match
match 类似 TypeScript 的 switch:
:= 1
:
0:
1:
2, 3:
:
_ 表示默认分支。
match 不需要 break,并且不会发生分支穿透。
10. 循环
For 循环
输出范围为 0 到 4。
指定起点和终点:
指定步长:
While 循环
:= 0
+= 1
Continue 和 Break
continue
break
11. 函数
普通函数
-> :
return +
无返回值函数
-> :
默认参数
-> :
return %
静态函数
-> :
return
调用:
:=
GDScript 不支持函数重载。
下面的写法无效:
# 不允许声明两个同名函数
-> :
return
-> :
return
通常通过不同函数名、默认参数或更通用的参数类型解决。
12. Lambda 与 Callable
GDScript 使用 Callable 表示可调用对象。
: = -> :
return * 2
: =
将普通函数作为 Callable:
-> :
:=
也可以直接引用函数:
: =
13. 枚举
匿名枚举
命名枚举
使用枚举:
: =
枚举值底层是整数。
可以显式指定数值:
14. 类与继承
一个 .gd 文件通常对应一个类。
: = 0
-> :
+= 1
使用:
:=
构造函数
GDScript 使用 _init() 作为构造函数:
:
-> :
=
创建对象:
:=
继承
-> :
子类:
-> :
调用父类同名方法:
-> :
GDScript 只支持单继承。
访问修饰符
GDScript 没有:
publicprivateprotected
通常使用下划线表示内部成员:
: = 0
-> :
return * 2
这只是命名约定,不会真正限制访问。
15. Getter 与 Setter
: = 0
: :
:
return
:
=
使用方式和普通变量相同:
= -10
# 0
也可以直接使用属性自身作为后备存储:
: = 0:
:
=
:
return
16. 类型判断与类型转换
is
is 类似 TypeScript 的 instanceof:
as
:=
对象转换失败时,as 可能返回 null。
更安全的写法:
: =
基础类型转换
:=
:=
:=
17. Null
GDScript 没有 undefined,只有 null。
: =
对象类型可以保存 null。
以下值类型不能使用 null:
: = 0
: = 0.0
: =
GDScript 没有 TypeScript 的可选链:
object?.method();
需要显式判断:
GDScript也没有 ?? 空值合并运算符,可以使用三元表达式:
:=
18. Signal
Signal 类似类型化的事件。
定义 Signal
发出 Signal
连接 Signal
-> :
-> :
也可以连接 Lambda:
断开 Signal
19. Await
GDScript 使用 await 等待 Signal。
-> :
await .
等待自定义 Signal:
-> :
await
GDScript 没有 JavaScript 的 Promise,也没有 Promise.all()。
异步流程通常围绕 Signal 组织。
20. 注解
@export
将属性暴露到 Godot Inspector:
: = 100.0
: =
限制数字范围:
: = 50
限制步长:
: = 1.0
枚举选项:
: = 0
资源类型:
:
:
@onready
等待当前 Node 进入场景树后初始化:
: = $
: = %
它常用于获取子节点,因为脚本初始化时子节点可能尚未准备完成。
21. Preload 与 Load
preload
编译时预加载:
:=
:=
preload() 的路径必须是常量字符串。
load
运行时动态加载:
:=
:=
建议为结果添加类型:
:=
22. 错误处理
GDScript 没有 try/catch。
Godot API 通常通过以下方式表示错误:
- 返回
Error - 返回
null - 返回
false - 输出错误日志
常用调试函数:
断言:
assert
assert() 主要用于开发阶段,不应该代替正常的业务错误处理。
23. 值类型与引用类型
常见值类型包括:
intfloatboolStringVector2Vector3Color
复制值类型会得到独立副本:
:=
:=
= 100.0
# 10
常见引用类型包括:
ArrayDictionaryObjectNodeResourceRefCounted
复制引用类型变量通常只是复制引用。
24. TypeScript 开发者需要注意的差异
GDScript 没有这些 TypeScript 特性
undefined- 可选链
?. - 空值合并
?? - 接口
interface - 联合类型
- 交叉类型
- 用户自定义泛型
- 函数重载
- 访问修饰符
- 装饰器系统
- ES Module
- 异常捕获
try/catch - Promise
- 对象解构
- 数组展开语法
对应替代方式
| TypeScript 特性 | GDScript 替代方式 |
|---|---|
interface | 基类、Resource、鸭子类型 |
import | class_name、preload() |
| Promise | Signal + await |
try/catch | 返回值、Error、null 检查 |
private | 下划线命名约定 |
T | null | 对象类型直接允许 null |
Array<T> | Array[T] |
Map<K, V> | Dictionary[K, V] |
instanceof | is |
| 类型断言 | as |
switch | match |
25. 命名规范
Godot 官方风格通常使用:
: = 3
: = 10.0
: = 0
: = 0
-> :
pass
-> :
return 1.0
命名约定:
| 内容 | 风格 |
|---|---|
| 类名 | PascalCase |
| 函数 | snake_case |
| 变量 | snake_case |
| 常量 | UPPER_SNAKE_CASE |
| 内部成员 | _snake_case |
| 文件名 | snake_case.gd |
| Signal | snake_case,通常使用过去式 |
Signal 示例:
26. 完整语法示例
: = 100
: = 0
: = :
:
=
=
: :
:
return
-> :
=
-> :
return
=
-> :
= 0
-> :
return >=
-> :
return
使用:
:=