Giới thiệu: Từ keyword đến annotation
Godot 4 đã thay thế nhiều keyword GDScript bằng các annotation có tiền tố @. Đây là một phần của nỗ lực lớn hơn nhằm làm cho cú pháp GDScript gọn gàng và nhất quán hơn. Ba thay đổi quan trọng nhất là:
export→@exportonready→@onreadytool→@tool
Annotation được đặt ở dòng trước (hoặc cùng dòng với) khai báo mà chúng chỉnh sửa. Godot 4 cũng giới thiệu nhiều biến thể annotation mới như @export_range, @export_group và @export_category mà Godot 3 không có. Hướng dẫn này sẽ đề cập tất cả chúng.
@export cơ bản
Annotation @export làm cho một biến hiển thị trong Inspector của Godot và cho phép bạn cấu hình giá trị mà không cần chỉnh sửa mã. Godot tự động chọn widget editor phù hợp dựa trên kiểu của biến.
@export var speed: float = 300.0
@export var player_name: String = "Player"
@export var health: int = 100
@export var color: Color = Color.WHITE
@export var texture: Texture2D
@export var scene: PackedScene
Mẹo: Luôn thêm chú thích kiểu cho các biến được export. Nhờ đó Inspector sẽ hiển thị đúng widget (ví dụ bộ chọn màu cho Color, một slot resource cho Texture2D).
@export_range — Thanh trượt số
@export_range giới hạn một giá trị số trong khoảng nhỏ nhất và lớn nhất, đồng thời hiển thị một thanh trượt trong Inspector. Bạn cũng có thể chỉ định bước nhảy và các gợi ý như "or_greater" hoặc "or_less".
@export_range(0, 100) var health: int = 100
@export_range(0.0, 1.0, 0.01) var volume: float = 0.8
@export_range(0, 1000, 1, "or_greater") var damage: int = 10
Gợi ý "or_greater" cho phép nhập các giá trị vượt quá mức tối đa, trong khi phạm vi thanh trượt vẫn được giữ nguyên. Tương tự, "or_less" cho phép các giá trị thấp hơn mức tối thiểu.
@export_enum — Menu thả xuống
@export_enum tạo ra một danh sách thả xuống trong Inspector. Khi dùng với String, tên của tùy chọn được chọn sẽ được lưu. Khi dùng với int, bạn có thể gán các giá trị cụ thể.
# Stores the string name: "Warrior", "Mage", or "Rogue"
@export_enum("Warrior", "Mage", "Rogue") var character_class: String
# Stores the integer value: 0, 1, or 2
@export_enum("Easy:0", "Normal:1", "Hard:2") var difficulty: int = 1
@export_file và @export_dir — Đường dẫn tệp/thư mục
@export_file hiển thị một hộp thoại chọn tệp trong Inspector. Bạn có thể lọc theo phần mở rộng của tệp. @export_dir hiển thị một hộp thoại chọn thư mục.
@export_file("*.tscn") var next_level: String
@export_dir var save_directory: String
Chuỗi bộ lọc dùng mẫu glob. Nhiều bộ lọc có thể được tách bằng dấu phẩy: "*.png,*.jpg".
@export_multiline và @export_placeholder
@export_multiline cung cấp một vùng văn bản lớn cho các chuỗi nhiều dòng (lý tưởng cho hội thoại hoặc mô tả). @export_placeholder hiển thị văn bản gợi ý trong ô khi nó trống.
@export_multiline var description: String
@export_placeholder("Enter name...") var player_name: String
@export_group và @export_subgroup — Sắp xếp thuộc tính trong Inspector
@export_group tạo ra một tiêu đề nhóm có thể thu gọn trong Inspector. Tất cả các biến @export tiếp theo thuộc về nhóm này, cho đến nhóm hoặc danh mục kế tiếp. @export_subgroup lồng vào bên trong nhóm hiện tại.
@export_group("Movement")
@export var speed: float = 300.0
@export var jump_force: float = 400.0
@export_group("Combat")
@export var attack_damage: int = 10
@export var defense: int = 5
@export_subgroup("Ranged")
@export var projectile_speed: float = 500.0
Nhóm và nhóm con chỉ phục vụ mục đích tổ chức — chúng không ảnh hưởng đến việc truy cập biến trong mã, mà chỉ ảnh hưởng đến cách các thuộc tính xuất hiện trong Inspector.
@export_category — Tiêu đề danh mục in đậm
@export_category tạo ra một tiêu đề danh mục in đậm ở cấp cao nhất trong Inspector. Khác với nhóm, danh mục không thể thu gọn và đóng vai trò như một ranh giới trực quan mạnh mẽ giữa các tập thuộc tính không liên quan đến nhau.
@export_category("Player Stats")
@export var level: int = 1
@export var experience: int = 0
@export với tham chiếu Node
Bạn có thể export một NodePath để designer chọn một node từ cây scene. Trong Godot 4.2+, bạn có thể export trực tiếp một tham chiếu node có kiểu — không cần NodePath.
# Classic NodePath export
@export var target_path: NodePath
# Godot 4.2+: typed node export (direct reference, no NodePath needed)
@export var sprite: Sprite2D
@export var collision: CollisionShape2D
Export node có kiểu là cách tiếp cận được khuyến nghị trong Godot 4 hiện đại. Inspector hiển thị một bộ chọn node đã được lọc theo kiểu bạn chỉ định, và bạn có được tính năng tự động hoàn thành đầy đủ trong trình soạn thảo script.
@export_flags — Hộp kiểm bitmask
@export_flags tạo ra một tập hộp kiểm, trong đó mỗi tùy chọn tương ứng với một bit trong một số nguyên. Godot cũng cung cấp các export flag tích hợp sẵn cho các layer vật lý và render.
# Custom flags: Fire=1, Water=2, Earth=4, Wind=8
@export_flags("Fire", "Water", "Earth", "Wind") var elements: int
# Built-in physics layer flags
@export_flags_2d_physics var collision_layers: int
@export_flags_2d_render var render_layers: int
@export_flags_3d_physics var collision_layers_3d: int
@onready — Khởi tạo trì hoãn
@onready trì hoãn việc khởi tạo một biến cho đến khi node được thêm vào cây scene (tương đương với việc gán trong _ready()). Điều này là thiết yếu khi bạn tham chiếu các node con bằng $, vì các node con chưa sẵn sàng tại thời điểm phân tích cú pháp.
# Godot 3 (old syntax):
# onready var sprite = $Sprite2D
# Godot 4:
@onready var sprite: Sprite2D = $Sprite2D
@onready var anim: AnimationPlayer = $AnimationPlayer
@onready var label: Label = $UI/ScoreLabel
Thực hành tốt nhất: Luôn khai báo kiểu cho các biến @onready. Điều này bật tính năng tự động hoàn thành và bắt lỗi kiểu tại thời điểm phân tích cú pháp thay vì tại thời điểm chạy.
@tool — Chạy script trong editor
@tool cho phép một script chạy bên trong trình soạn thảo Godot (không chỉ khi chạy game). Điều này rất mạnh mẽ để tạo các bản xem trước tùy chỉnh, gizmo và các thuộc tính cập nhật trực tiếp. Đặt nó ở đầu script, trước extends.
@tool
extends Node2D
@export var radius: float = 100.0:
set(value):
radius = value
queue_redraw() # Redraw in editor when value changes
func _draw() -> void:
draw_circle(Vector2.ZERO, radius, Color.WHITE)
Lưu ý: Hãy cẩn thận với các script @tool. Mã trong _process() và _physics_process() sẽ chạy trong editor. Dùng Engine.is_editor_hint() để bảo vệ phần logic chỉ dành cho game.
Các annotation khác
@icon
Đặt một biểu tượng tùy chỉnh cho kiểu node của script trong Scene dock và trong hộp thoại "Tạo Node".
@icon("res://icons/enemy.svg")
extends CharacterBody2D
@warning_ignore
Ngăn các cảnh báo GDScript cụ thể cho câu lệnh kế tiếp. Hữu ích khi bạn cố ý che khuất (shadow) một biến hoặc có một tham số không được sử dụng.
@warning_ignore("unused_parameter")
func _on_body_entered(body: Node2D) -> void:
queue_free()
@warning_ignore("shadowed_variable")
var size: int = 10
@static_unload
Đánh dấu một script để Godot có thể giải phóng nó khỏi bộ nhớ khi không còn instance nào tồn tại. Điều này có thể giảm mức sử dụng bộ nhớ cho các script chỉ được dùng tạm thời. Script không được có biến hoặc dữ liệu tĩnh cần được giữ lại.
@static_unload
extends RefCounted
# This script can be safely unloaded when not in use
Thực hành tốt nhất về kiểu tĩnh
Mặc dù không phải là annotation, các gợi ý kiểu tĩnh có liên quan chặt chẽ với chúng và được khuyến nghị mạnh mẽ trong Godot 4. Chúng cải thiện tính năng tự động hoàn thành, cho phép kiểm tra lỗi tại thời điểm biên dịch và có thể cải thiện hiệu năng.
# Variable type annotations
var speed: float = 300.0
var player: CharacterBody2D = null
var items: Array[String] = []
var scores: Dictionary = {}
# Function return types and parameter types
func get_damage() -> int:
return attack - defense
func apply_force(direction: Vector2, strength: float) -> void:
velocity += direction * strength
# Type inference with :=
var pos := Vector2(100, 200) # Inferred as Vector2
Lưu ý: Hãy cẩn thận với := trong vòng lặp for khi bạn duyệt qua các array không có kiểu. Thay vào đó, hãy dùng chú thích kiểu tường minh: for item: String in array.
Bảng tra cứu nhanh: chuyển từ Godot 3 sang 4
Tham khảo nhanh để chuyển đổi cú pháp export của Godot 3 sang annotation của Godot 4:
| Godot 3 | Godot 4 | Ghi chú |
|---|---|---|
export var x |
@export var x |
Export cơ bản |
export(int, 0, 100) var hp |
@export_range(0, 100) var hp: int |
Khoảng giá trị kèm gợi ý kiểu |
export(String, "A", "B") var x |
@export_enum("A", "B") var x: String |
Dropdown enum |
export(String, FILE) var path |
@export_file var path: String |
Bộ chọn tệp |
export(String, MULTILINE) var text |
@export_multiline var text: String |
Vùng văn bản nhiều dòng |
export(int, FLAGS, ...) var f |
@export_flags(...) var f: int |
Flag bitmask |
onready var x = $Node |
@onready var x: Type = $Node |
Khởi tạo trì hoãn |
tool |
@tool |
Chạy trong editor |
| Không có sẵn | @export_group("...") |
Mới trong Godot 4 |
| Không có sẵn | @export_category("...") |
Mới trong Godot 4 |
| Không có sẵn | @export_subgroup("...") |
Mới trong Godot 4 |
Godot MCP Pro hiểu tất cả annotation @export
Godot MCP Pro có thể tạo script với các export được khai báo kiểu chính xác, đọc và chỉnh sửa các annotation export hiện có, và kiểm tra các thuộc tính được export của mọi node trong scene của bạn — tất cả bằng AI.
- create_script
- edit_script
- read_script
- get_node_properties
- get_scene_exports
- update_property