上一节聊了 GDScript 是什么,这篇正式进入语法。变量和数据类型是写脚本的第一道坎,好消息是 GDScript 的变量系统比 C# 宽松得多,写起来很顺手,但也有一些自己的规则和坑,需要单独搞清楚。
一、用 var 声明变量
GDScript 里声明变量不用写类型,直接 var 名字 = 值 就行。
gdscript
var health = 100
var speed = 5.5
var player_name = "Tom"
var is_alive = true
从这些例子能看出来,变量的类型由赋给它的值自动决定。100 是整数,所以 health 是 int;5.5 是浮点数,所以 speed 是 float;带引号的是字符串,所以 player_name 是 String;true 和 false 是布尔值,所以 is_alive 是 bool。
这种"不写类型,让编译器猜"的方式在 GDScript 里叫动态类型 。它省事,但有个小问题:变量的类型在运行时才确定,有时候编辑器没法提前帮你发现类型错误。比如你写 health = "一百",编辑器不会在写的时候就报错,要等运行到这一行才崩。不过 Godot 4 对这种动态类型的检查已经比 3 代好了不少,至少会给出警告。
二、基础数据类型
GDScript 的基础类型就几种,下面分别过一下。
1. int(整数)
就是整数,正负都行,没有小数点。
gdscript
var age = 25
var enemies = 10
注意 GDScript 的 int 是 64 位有符号整数,范围比 C# 的 int(32 位)大得多,基本不用担心溢出。
2. float(浮点数)
带小数点的数字。在 GDScript 里,只要数里有小数点,就是 float。
gdscript
var pi = 3.14
var gravity = 9.8
有一点和 C# 不一样:C# 里写 float f = 5.0f 要加后缀 f,GDScript 不用,直接写 5.0 就是浮点数。写 5 就是整数,别搞混。
3. bool(布尔值)
只有 true 和 false 两个值。条件判断、开关状态都靠它。
gdscript
var can_jump = true
var has_key = false
4. String(字符串)
字符串用双引号或单引号都可以,但习惯上双引号多。
gdscript
var name = "Godot"
var msg = '你好'
字符串支持拼接,可以用加号,也可以用 % 或 format() 格式化,后面讲字符串操作时细说。
三、Godot 特有的内置类型
除了基础类型,Godot 还内置了一堆和游戏开发密切相关的类型,比如向量、颜色、变换等。这些在写游戏逻辑时用得非常多。
1. Vector2 和 Vector3
Vector2 表示 2D 坐标或二维向量,Vector3 表示 3D 坐标或三维向量。它们都是结构体类型,直接赋值即可。
gdscript
var pos2 = Vector2(100, 50)
var pos3 = Vector3(1.0, 2.0, 3.0)
也可以分别访问分量:
gdscript
var pos = Vector2(3, 4)
var x = pos.x # 3
var y = pos.y # 4
2D 游戏里,物体的位置、移动方向基本都是 Vector2;3D 则是 Vector3。后面写移动和碰撞时几乎离不开它们。
2. Color(颜色)
表示 RGBA 颜色,常用在调制颜色、粒子颜色等。
gdscript
var red = Color(1, 0, 0) # 红色,不透明
var translucent = Color(1, 1, 1, 0.5) # 半透明白
Godot 还提供了一些预设颜色常量,比如 Color.RED、Color.GREEN 等。
3. 其他常用类型
Transform2D/Transform3D:变换矩阵,通常在处理节点位置旋转缩放时内部使用。Rect2:矩形,常用于碰撞区域、UI 布局。AABB:3D 轴对齐包围盒。Array和Dictionary:复合类型,下面单独讲。
这些类型不用死记,用到的时候按 F1 查就行。
四、复合类型:数组与字典
数组和字典是 GDScript 里最常用的两个容器,和 C# 的 List<T> / Dictionary<K,V> 类似,但语法更接近 Python。
1. Array(数组)
数组用方括号 [] 创建,里面可以放任意类型的元素,甚至混合类型。
gdscript
var numbers = [1, 2, 3, 4]
var mixed = [1, "two", 3.0, true]
访问元素用下标,从 0 开始:
gdscript
var first = numbers[0] # 1
数组有很多内置方法,比如 append() 添加元素、size() 获取长度、remove() 删除等。这个后面专门有篇笔记展开讲。
2. Dictionary(字典)
字典用花括号 {} 创建,以键值对的形式存储数据。
gdscript
var player = {
"name": "Tom",
"health": 100,
"position": Vector2(10, 20)
}
访问值用中括号加键:
gdscript
var hp = player["health"] # 100
字典特别适合存储结构化数据,比如从 JSON 解析出来的配置表。不过 GDScript 的字典是动态类型,访问不存在的键会返回 null 而不是报错,要留意。
五、类型推断与类型注解
前面说过 GDScript 默认是动态类型,但 Godot 4 引入了更强大的类型系统,允许你显式指定变量类型。
1. 类型推断
即使你不写类型,Godot 也会在编译时尽量推断。比如:
gdscript
var speed = 5.5 # 推断为 float
var name = "Tom" # 推断为 String
写的时候体验和动态类型一样,但 Godot 会记录下来,编辑时能给你更好的代码提示。
2. 类型注解
如果你想明确指定类型(也叫静态类型),可以在变量名后面加冒号和类型名:
gdscript
var speed: float = 5.5
var name: String = "Tom"
var pos: Vector2 = Vector2.ZERO
一旦写了类型注解,这个变量的类型就固定了。以后给它赋其他类型的值,编辑器会直接报错。
gdscript
var health: int = 100
health = "一百" # 报错:无法将 String 赋值给 int
类型注解的好处:
- 编辑器补全更准确
- 编译时能捕获更多错误
- 运行性能更好(GDScript 的静态类型在运行时更快)
我的习惯是:对于关键变量、成员变量,尽量写类型注解;临时局部变量可以根据情况省略。这样既保留灵活性,又能在重要地方获得保障。
六、常量与 @export 变量
1. const 常量
常量用 const 声明,必须在声明时赋值,之后不能改。
gdscript
const MAX_HEALTH = 100
const GRAVITY = 9.8
常量的值在编译时就确定了,所以不能写成运行时才计算的值,比如 const random_value = randf() 会报错。
2. @export 暴露到检查器
在 Unity 里,把变量设为 public 或加 [SerializeField] 就能在 Inspector 里看到并调整。Godot 对应的做法是加 @export 注解。
gdscript
extends Node2D
@export var move_speed: float = 100.0
@export var max_health: int = 5
这样 move_speed 和 max_health 就会出现在节点的 Inspector 面板里,你可以在编辑器中直接改数值,不用动代码。这个功能特别适合调参,比如移动速度、跳跃力度、敌人血量等。
注意:@export 只能用于脚本的成员变量,不能用于局部变量。而且如果变量没有类型注解,Godot 会尝试推断,但最好还是手动指定类型。
七、null 与空值判断
GDScript 里用 null 表示空值,类似 C# 的 null。没有赋值的变量,如果是基础类型(如 int、float、bool)会有默认零值;如果是引用类型(如节点、数组、字典)则默认为 null。
gdscript
var player = null
判断一个变量是否为空:
gdscript
if player == null:
print("玩家不存在")
Godot 4 还提供了 is null 的写法,但和 == null 等价,看个人习惯。
要注意的是,访问 null 对象的属性或方法会报运行时错误,比如:
gdscript
player.health = 100 # 如果 player 是 null,会报错
所以在操作可能为空的节点引用时,先判空是好习惯。
八、写个简单例子感受一下
这里用一个完整的脚本片段结束本篇,展示变量和类型在实际节点脚本中的使用:
gdscript
extends Node2D
# 暴露到检查器的变量
@export var move_speed: float = 200.0
@export var jump_force: float = 400.0
# 私有变量
var velocity: Vector2 = Vector2.ZERO
var is_on_floor: bool = false
func _ready():
# 初始化
velocity = Vector2.ZERO
print("初始化完成")
func _process(delta):
# 读取输入并处理移动(后面输入篇细讲)
# 注意:这四个动作需要在项目设置 -> 输入映射中手动定义
var input_dir = Input.get_vector("left", "right", "up", "down")
velocity = input_dir * move_speed
position += velocity * delta
在这个例子里,move_speed 用了 @export 和类型注解,velocity 是 Vector2 类型,delta 是 _process 自带的时间参数。这些都是 GDScript 变量使用的典型场景。
九、总结
GDScript 的变量系统比 C# 灵活,写起来省事,但也别完全放飞。我的建议是:
- 基础类型和内置类型要记熟,尤其是
Vector2、Vector3、Color。 - 关键变量加类型注解,能提前发现错误。
- 需要调参的变量加
@export,方便在编辑器里调整。 - 操作可能为空的引用时先判空。