Cheat sheet GDScript
Cập nhật lần cuối
Cơ bản và in kết quả
Một script kế thừa một kiểu node, và Godot tự gọi các hàm của nó cho bạn.
| Thao tác | Cú pháp |
|---|---|
| Gắn script vào một kiểu node | extends Node |
| Code chạy khi node bắt đầu | func _ready() -> void:
print("Hello, World!") |
| In giá trị không có ký tự phân cách | print("HP: ", hp) |
| In giá trị cách nhau bằng dấu cách | prints("a", "b", 3) |
| Chú thích | # This is a comment |
| Chú thích tài liệu | ## Shown in the editor's help |
| Chuỗi nhiều dòng | var text := """Line one
Line two""" |
| Báo lỗi | push_error("Health is negative") |
| Báo cảnh báo | push_warning("Old save file") |
Biến, hằng số và kiểu dữ liệu
Kiểu là tùy chọn. Thêm kiểu để editor kiểm tra lỗi, gợi ý code tốt hơn và code chạy nhanh hơn.
| Thao tác | Cú pháp |
|---|---|
| Biến (kiểu động) | var score = 0 |
| Biến có kiểu tĩnh | var speed: float = 200.0 |
| Tự suy ra kiểu tĩnh | var lives := 3 |
| Hằng số | const MAX_HP = 100 |
| Enum | enum State { IDLE, RUN, JUMP } |
| Dùng một giá trị enum | var state: State = State.IDLE |
| Giá trị vector và màu | var pos := Vector2(10, 20)
var tint := Color(1, 0, 0) |
| Tham chiếu đối tượng rỗng | var target: Node = null |
| Chuyển sang chuỗi, int hoặc float | str(42), int("42"), float("3.5") |
| Float sang int (bỏ phần thập phân) | int(3.9) # 3 |
| Kiểm tra kiểu | value is int, node is Sprite2D |
| Ép kiểu | var sprite := node as Sprite2D |
Toán tử
Các phép toán quen thuộc, cộng thêm từ tiếng Anh cho phép logic.
| Thao tác | Cú pháp |
|---|---|
| Cộng, trừ, nhân, chia | a + b, a - b, a * b, a / b |
| Chia lấy phần nguyên (int / int) | 7 / 2 # 3 |
| Phép chia lấy dư | 7 % 3, fmod(7.5, 2.0) |
| Lũy thừa | 2 ** 10 # 1024 |
| Gán kết hợp | x += 1, x -= 1, x *= 2, x /= 2 |
| So sánh | ==, !=, <, >, <=, >= |
| Logic | a and b, a or b, not a |
| Logic (dạng ký hiệu) | a && b, a || b, !a |
| If trên một dòng | var label := "win" if score > 10 else "lose" |
| Kiểm tra có nằm trong collection | "sword" in inventory |
| Thao tác bit | a & b, a | b, a ^ b, ~a, a << 1, a >> 1 |
Luồng điều khiển
Khối lệnh được xác định bằng thụt lề, giống Python. Mặc định Godot thụt lề bằng tab.
| Thao tác | Cú pháp |
|---|---|
| If, elif, else | if hp <= 0:
die()
elif hp < 20:
print("Low HP")
else:
print("OK") |
| If trên một dòng | if hp <= 0: die() |
| Lặp qua một khoảng | for i in range(5):
print(i) # 0 to 4 |
| Khoảng có điểm đầu, điểm cuối và bước nhảy | for i in range(10, 0, -2):
print(i) # 10, 8, 6, 4, 2 |
| Lặp lại n lần | for i in 3:
print(i) # 0, 1, 2 |
| Lặp qua một mảng | for item in items:
print(item) |
| Biến lặp có kiểu (Godot 4.2+) | for n: String in names:
print(n.to_upper()) |
| Vòng lặp while | while hp > 0:
hp -= 10 |
| Thoát hoặc bỏ qua một lần lặp | break, continue |
| Giữ chỗ cho khối lệnh rỗng | pass |
So khớp mẫu (match)
match chạy nhánh đầu tiên có mẫu khớp. Không có chuyện rơi xuống nhánh tiếp theo.
| Thao tác | Cú pháp |
|---|---|
| So khớp giá trị | match state:
State.IDLE:
print("idle")
State.RUN:
print("run") |
| Nhiều giá trị trong một nhánh | match key:
"w", "up":
move_up() |
| Nhánh mặc định (ký tự đại diện) | match n:
0:
print("zero")
_:
print("other") |
| Gán giá trị cho một tên | match cmd:
"quit":
get_tree().quit()
var other:
print("Unknown: ", other) |
| Mẫu mảng | match pos:
[0, 0]:
print("origin")
[var x, 0]:
print("on the x axis at ", x) |
| Mảng với phần đuôi bất kỳ | match args:
["move", ..]:
print("move command") |
| Mẫu dictionary | match item:
{"type": "coin", "value": var v}:
gold += v |
| Điều kiện phụ với when (Godot 4.4+) | match score:
var s when s >= 90:
print("A")
var s when s >= 75:
print("B")
_:
print("C") |
Hàm và lambda
Hàm cũng là giá trị: bạn có thể lưu, truyền đi và gắn sẵn đối số cho chúng.
| Thao tác | Cú pháp |
|---|---|
| Tham số và giá trị trả về có kiểu | func add(a: int, b: int) -> int:
return a + b |
| Không có giá trị trả về | func reset() -> void:
score = 0 |
| Đối số mặc định | func greet(who := "player") -> void:
print("Hi, ", who) |
| Hàm static | static func double(x: int) -> int:
return x * 2 |
| Lambda một dòng | var square := func(x): return x * x |
| Gọi một Callable | square.call(4) # 16 |
| Dùng hàm như một giá trị | var on_done := reset
on_done.call() |
| Gắn sẵn đối số | var add_ten := add.bind(10)
print(add_ten.call(5)) # 15 |
| Lambda nhiều dòng | var greet_all := func(names: Array) -> void:
for n in names:
print("Hi, ", n) |
| Chờ một bộ hẹn giờ | await get_tree().create_timer(1.0).timeout |
| Chờ một coroutine | var data = await fetch_data() |
Chuỗi
Các phương thức chuỗi trả về chuỗi mới và không bao giờ thay đổi chuỗi gốc.
| Thao tác | Cú pháp |
|---|---|
| Định dạng bằng % | "%s has %d HP" % [name, hp] |
| Hai chữ số thập phân | "%.2f" % 3.14159 # "3.14" |
| Định dạng bằng placeholder có tên | "{a} vs {b}".format({"a": 1, "b": 2}) |
| Nối bằng + | "Score: " + str(score) |
| Độ dài | text.length() |
| Chữ hoa hoặc chữ thường | text.to_upper(), text.to_lower() |
| Tách thành nhiều phần | "a,b,c".split(",") # ["a", "b", "c"] |
| Ghép các phần | ", ".join(["a", "b", "c"]) |
| Xóa khoảng trắng hai đầu | " hi ".strip_edges() # "hi" |
| Thay thế văn bản | text.replace("cat", "dog") |
| Tìm vị trí | text.find("lo") # -1 if missing |
| Bắt đầu hoặc kết thúc bằng | text.begins_with("Hi"), text.ends_with("!") |
| Chuỗi con | text.substr(0, 5) |
| Kiểm tra có chứa | "ell" in "Hello" # true |
Mảng
Mảng có thể dài ra hoặc ngắn lại. Mảng có kiểu chỉ nhận phần tử đúng kiểu đó.
| Thao tác | Cú pháp |
|---|---|
| Tạo mảng bằng literal (nhiều kiểu) | var items = [1, "two", 3.0] |
| Mảng có kiểu | var scores: Array[int] = [10, 20, 30] |
| Đọc theo chỉ số (số âm đếm từ cuối) | scores[0], scores[-1] |
| Thêm vào cuối | scores.append(40), scores.push_back(40) |
| Chèn tại một chỉ số | scores.insert(0, 5) |
| Xóa và trả về phần tử cuối | var last = scores.pop_back() |
| Xóa theo giá trị hoặc theo chỉ số | scores.erase(20), scores.remove_at(0) |
| Kiểm tra có chứa, tìm chỉ số | scores.has(30), scores.find(30) |
| Độ dài, kiểm tra rỗng | scores.size(), scores.is_empty() |
| Sắp xếp | scores.sort() |
| Sắp xếp theo quy tắc riêng | enemies.sort_custom(func(a, b): return a.hp < b.hp) |
| Ánh xạ (map) | scores.map(func(x): return x * 2) |
| Lọc (filter) | scores.filter(func(x): return x > 15) |
| Gộp (reduce) | scores.reduce(func(acc, x): return acc + x, 0) |
| Cắt mảng (không gồm vị trí cuối) | scores.slice(1, 3) |
Dictionary
Các cặp khóa và giá trị. Khóa có thể thuộc bất kỳ kiểu nào; phổ biến nhất là chuỗi.
| Thao tác | Cú pháp |
|---|---|
| Tạo dictionary bằng literal | var stats = {"hp": 100, "mp": 30} |
| Dictionary có kiểu (Godot 4.4+) | var prices: Dictionary[String, int] = {"sword": 50} |
| Đọc hoặc ghi một khóa | stats["hp"], stats["xp"] = 50 |
| Đọc với giá trị mặc định | stats.get("luck", 0) |
| Kiểm tra có khóa | stats.has("hp"), "hp" in stats |
| Xóa một khóa | stats.erase("mp") |
| Các khóa và các giá trị | stats.keys(), stats.values() |
| Số phần tử | stats.size() |
| Gộp dictionary khác (true để ghi đè) | stats.merge({"luck": 5}), stats.merge(bonus, true) |
| Lặp qua các khóa | for key in stats:
print(key, " = ", stats[key]) |
Lớp và annotation
Mỗi script là một lớp. Annotation bắt đầu bằng @.
| Thao tác | Cú pháp |
|---|---|
| Đặt tên toàn cục cho lớp | class_name Player
extends CharacterBody2D |
| Hàm khởi tạo | func _init(start_hp := 100) -> void:
hp = start_hp |
| Tạo instance | var p := Player.new() |
| Lớp lồng bên trong | class Item:
var name := ""
var price := 0 |
| Gọi phiên bản của lớp cha cho phương thức này | func _ready() -> void:
super()
print("child ready") |
| Gọi phương thức khác của lớp cha | super.take_damage(10) |
| Biến static (Godot 4.1+) | static var count := 0 |
| Hiện trong Inspector | @export var speed := 300.0 |
| Hiện với thanh trượt có khoảng giá trị | @export_range(0, 100) var volume := 50 |
| Lấy node con khi sẵn sàng | @onready var sprite: Sprite2D = $Sprite2D |
| Setter và getter | var hp := 100:
set(value):
hp = clampi(value, 0, 100)
get:
return hp |
| Chạy script trong editor | @tool |
Signal
Signal là first-class: khai báo rồi emit, kết nối và chờ chúng trực tiếp.
| Thao tác | Cú pháp |
|---|---|
| Khai báo signal | signal died |
| Signal có đối số kèm kiểu | signal health_changed(old_hp: int, new_hp: int) |
| Phát signal | died.emit() |
| Phát kèm đối số | health_changed.emit(100, 80) |
| Kết nối tới một phương thức | player.died.connect(_on_player_died) |
| Kết nối một lambda | button.pressed.connect(func(): print("Clicked")) |
| Truyền thêm đối số | button.pressed.connect(_on_pressed.bind("start")) |
| Chỉ kích hoạt một lần | timer.timeout.connect(_on_timeout, CONNECT_ONE_SHOT) |
| Ngắt kết nối | player.died.disconnect(_on_player_died) |
| Kiểm tra kết nối | player.died.is_connected(_on_player_died) |
| Chờ một signal | await player.died |
Node và vòng đời
Các callback Godot gọi trên node của bạn, và các lời gọi bạn thực hiện trên cây scene.
| Thao tác | Cú pháp |
|---|---|
| Đối tượng được tạo (trước khi vào cây) | func _init() -> void:
print("created") |
| Node và các node con đã sẵn sàng | func _ready() -> void:
print("ready") |
| Mỗi khung hình | func _process(delta: float) -> void:
position.x += 100.0 * delta |
| Mỗi nhịp vật lý | func _physics_process(delta: float) -> void:
velocity.y += 980.0 * delta
move_and_slide() |
| Đầu vào mà UI không dùng tới | func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("jump"):
jump() |
| Lấy node theo đường dẫn | get_node("Sprite2D"), $Sprite2D |
| Đường dẫn có dấu cách, tên duy nhất | $"UI/Health Bar", %HealthBar |
| Kiểm tra một input action | Input.is_action_pressed("move_right") |
| Tạo instance của một scene | var enemy := preload("res://enemy.tscn").instantiate()
add_child(enemy) |
| Xóa node an toàn | queue_free() |
| Node cha và các node con | get_parent(), get_children() |
| Chuyển scene | get_tree().change_scene_to_file("res://main.tscn") |
Cú pháp GDScript mà bạn cần khi làm game với Godot, gom trong một trang. Cheat sheet GDScript này là bảng tra cứu nhanh cho Godot 4: biến và kiểu tĩnh, toán tử, luồng điều khiển và match, hàm và lambda, chuỗi, mảng và dictionary, lớp, signal, cùng các callback của node mà Godot gọi mỗi khung hình.
Mọi thứ ở đây đều là cú pháp Godot 4, nên bạn sẽ thấy @export, @onready, died.emit() và await thay vì các dạng của Godot 3. Sao chép phần bạn cần vào script, hoặc chạy thử các đoạn code ngay trong playground GDScript: đặt chúng vào trong _ready() và chạy trên trình duyệt, không cần cài Godot.
Câu hỏi thường gặp về cheat sheet GDScript
Cheat sheet GDScript này có miễn phí không?
Có. Cheat sheet GDScript này hoàn toàn miễn phí, không cần đăng ký. Lưu trang lại và quay lại bất cứ khi nào bạn cần đúng cú pháp của một signal, một mẫu match hay một phương thức mảng.
Cheat sheet này dành cho Godot 4 hay Godot 3?
@export và @onready thay cho từ khóa export và onready, died.emit() và died.connect(callable) thay cho emit_signal("died") và connect dựa trên chuỗi, await thay cho yield, và super() thay cho .method(). Các hàng ghi 4.1+, 4.2+ hoặc 4.4+ cần Godot từ phiên bản đó trở lên.= và := trong GDScript khác nhau thế nào?
var x = 5 tạo một biến động, sau này có thể chứa bất kỳ kiểu nào. var x := 5 suy ra kiểu từ giá trị (ở đây là int) và cố định kiểu đó, nên gán một chuỗi về sau sẽ báo lỗi. var x: int = 5 khai báo kiểu một cách tường minh. Kiểu tĩnh giúp editor báo lỗi sớm, gợi ý code tốt hơn và code chạy nhanh hơn.Signal trong GDScript hoạt động thế nào?
signal died, phát nó bằng died.emit(), và phản hồi từ một node khác bằng player.died.connect(_on_player_died). Bạn có thể kết nối một lambda thay cho phương thức, gắn thêm đối số bằng .bind(), hoặc tạm dừng một hàm cho đến khi signal được phát bằng await player.died.GDScript có giống Python không?
for ... in, if/elif/else cùng các từ tiếng Anh như and, or và not. Nhưng GDScript là một ngôn ngữ riêng, được tạo ra cho Godot. Nó có kiểu tĩnh tùy chọn, signal, annotation như @export, và truy cập trực tiếp node bằng $.Có thể luyện tập GDScript online không?
_ready() chạy một lần. Khi muốn học có lộ trình, khóa học GDScript tương tác miễn phí của Coddy đưa bạn đi từng bước từ biến và hàm đến lớp và signal.