## Giới thiệu ngắn Mục tiêu bài viết này là đưa bạn từ hiểu khái niệm cơ bản về Scene, Node và Resource trong Godot đến việc tạo một prototype mini game "nhặt vật phẩm" (collectible pickup). Bài viết phù hợp cho người mới bắt đầu muốn hiểu cách tổ chức scene tree, cách dùng Inspector để cấu hình, cách viết GDScript nhỏ để điều khiển gameplay, cách gửi và nhận signal, và cách đóng gói scene để tái sử dụng cho prototype nhanh. Tất cả khái niệm chính về Scene/Node/Resource được đối chiếu với tài liệu chính thức của Godot để giảm nhầm lẫn giữa khái niệm và những chức năng nâng cao (ví dụ: không đi sâu vào tối ưu remove_child, AnimationTree, rendering SSIL/TAA, plugin toàn cầu hay ObjectDB). Độc giả nên kiểm tra tài liệu chính thức khi cần cập nhật vì API và chi tiết có thể thay đổi theo phiên bản Godot; tham khảo tài liệu chính thức để biết chi tiết phiên bản hiện tại [1][3][4].

1:04 ước tính · Chưa có giọng vi-VN
Bài này dùng một mini game nhặt vật phẩm để giải thích ba khái niệm nền tảng trong Godot: Node là building block, Scene là một cây Node có thể lưu và tái sử dụng, còn Resource là dữ liệu có thể dùng chung giữa nhiều scene hoặc node. Mục tiêu không phải tạo game hoàn chỉnh mà xây một prototype đủ rõ để bạn hiểu scene tree, Inspector, custom Resource, instancing và signal.
Phần hình ảnh được rà theo đúng ngữ cảnh: sơ đồ Node/Scene chỉ nằm ở phần kiến trúc, ảnh Inspector Resource nằm ở phần Resource, sơ đồ instancing nằm ở phần tái sử dụng Scene, giao diện Signals nằm cạnh phần kết nối signal, Label Inspector nằm ở HUD và Debugger nằm ở troubleshooting. Các ảnh editor chung chung không chứng minh nội dung đã được loại khỏi body.

Node là đơn vị cơ bản của scene tree. Một node có thể đảm nhiệm transform 2D, va chạm, sprite, UI, audio hoặc logic. Node có parent và child, vì vậy hành vi phức tạp thường được tạo bằng cách ghép nhiều node nhỏ thay vì một object khổng lồ.
Scene là một cây node được lưu thành tài nguyên có thể instance. Player, Item, HUD hay cả một level đều có thể là scene riêng. Khi một scene được dùng lại nhiều lần, bạn có thể sửa cấu trúc gốc ở một nơi thay vì copy thủ công.
Resource phù hợp cho dữ liệu như stats item, texture, cấu hình vũ khí, thông số enemy hoặc theme. Resource không thay Scene: Scene mô tả object/cấu trúc trong tree, Resource chủ yếu lưu dữ liệu có thể được tham chiếu và tái sử dụng.
Prototype gồm Main, Player, nhiều Item và HUD. Mỗi Item là một scene riêng, nhưng dữ liệu tên/điểm/texture nằm trong ItemData Resource. Khi Player đi vào vùng va chạm của Item, Item phát signal picked_up; GameManager nhận signal, cộng điểm và cập nhật HUD.
res://
scenes/
main.tscn
player.tscn
item.tscn
hud.tscn
scripts/
player.gd
item.gd
item_data.gd
game_manager.gd
hud.gd
data/
coin.tres
gem.tresMain có thể dùng cây đơn giản: Main(Node2D) → Player, Items(Node2D), HUD(CanvasLayer), GameManager(Node). Tách Items thành container giúp spawn, tìm và dọn vật phẩm dễ hơn.

Custom Resource giúp tách dữ liệu khỏi logic. Với Godot 4, một ItemData cơ bản có thể viết như sau:
extends Resource
class_name ItemData
@export var item_name: String = "Item"
@export var value: int = 10
@export var texture: Texture2DSau khi script được Godot nhận diện, tạo Resource mới kiểu ItemData rồi lưu thành coin.tres, gem.tres. Hai file có thể dùng cùng Item scene nhưng mang texture và điểm khác nhau. Đây là lợi ích chính: thay dữ liệu mà không duplicate logic.
Ảnh Inspector ở đây chỉ dùng để minh họa đúng bản chất Resource/property có thể được chỉnh trong editor; nó không được mô tả như screenshot của chính coin.tres.
Với Godot 4, cấu trúc gọn có thể là Item(Area2D) → Sprite2D + CollisionShape2D. Area2D phù hợp cho trigger nhặt vật phẩm.
extends Area2D
signal picked_up(data: ItemData)
@export var data: ItemData
@onready var sprite: Sprite2D = $Sprite2D
func _ready() -> void:
if data and data.texture:
sprite.texture = data.texture
body_entered.connect(_on_body_entered)
func _on_body_entered(body: Node) -> void:
if body.is_in_group("player"):
picked_up.emit(data)
queue_free()Item không cần biết tổng điểm hiện tại. Nó chỉ chịu trách nhiệm phát hiện Player, phát sự kiện với dữ liệu của chính nó rồi tự giải phóng. Việc cộng điểm thuộc GameManager. Tách trách nhiệm như vậy làm scene Item dễ tái sử dụng hơn.
Trong Godot 4, Player 2D thường dùng CharacterBody2D. Thêm Sprite2D và CollisionShape2D, sau đó đưa Player vào group player trong Inspector hoặc bằng code.
extends CharacterBody2D
@export var speed := 220.0
func _ready() -> void:
add_to_group("player")
func _physics_process(_delta: float) -> void:
var input_dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
velocity = input_dir * speed
move_and_slide()Group giúp Item nhận diện Player mà không phụ thuộc tên node hoặc đường dẫn scene. Với prototype lớn hơn, bạn có thể dùng collision layers/masks để giới hạn loại body được phát hiện trước khi kiểm group.

GameManager có thể preload Item scene, tạo instance và gán Resource tương ứng:
extends Node
@onready var items_container: Node2D = $"../Items"
@onready var hud = $"../HUD"
var item_scene: PackedScene = preload("res://scenes/item.tscn")
var score := 0
func spawn_item(position: Vector2, data: ItemData) -> void:
var item = item_scene.instantiate()
item.position = position
item.data = data
item.picked_up.connect(_on_item_picked_up)
items_container.add_child(item)
func _on_item_picked_up(data: ItemData) -> void:
if not data:
return
score += data.value
hud.update_score(score)Điểm quan trọng là Scene và Resource đóng hai vai trò riêng. item.tscn chứa cấu trúc và hành vi chung; coin.tres, gem.tres chứa biến thể dữ liệu. Bạn có thể tạo hàng chục item mà không nhân bản script.

Signal cho phép Item báo một sự kiện mà không cần biết GameManager nằm ở đâu. Đây là khác biệt quan trọng so với việc Item tự tìm /root/Main/GameManager và gọi thẳng hàm. Khi scene được tái sử dụng ở level khác, coupling thấp giúp ít phải sửa.
Với item spawn động, kết nối signal bằng code ngay sau instantiate() thường rõ ràng. Với node tồn tại cố định trong scene, kết nối qua Editor cũng hợp lý. Hai cách không cạnh tranh nhau; chọn theo lifecycle của object.

HUD tối giản có thể là CanvasLayer chứa Label:
extends CanvasLayer
@onready var score_label: Label = $ScoreLabel
func update_score(value: int) -> void:
score_label.text = "Score: %d" % valueGameManager giữ dữ liệu score, còn HUD chỉ hiển thị. Nếu UI sau này đổi sang progress bar, animation hoặc nhiều label, logic nhặt Item không cần thay đổi.
picked_up(data) rồi queue_free().data.value.Flow này nhỏ nhưng đã chứa pattern có thể mở rộng sang coin, health pickup, key item, loot hoặc trigger nhiệm vụ.
Inspector nên được dùng để chỉnh dữ liệu thay vì hard-code mọi thứ: speed của Player, ItemData của từng instance, CollisionShape2D, texture, vị trí spawn hoặc text UI. Khi một property là biến thiết kế thường xuyên thay đổi, export nó giúp iteration nhanh hơn.
Tuy nhiên đừng export mọi biến nội bộ. Những state như velocity tạm thời, cache hoặc reference runtime không nhất thiết cần xuất hiện trong Inspector. Inspector càng sạch thì prototype càng dễ đọc.
Giữ Player, Item và HUD thành scene riêng nếu chúng có lifecycle hoặc cần tái sử dụng độc lập. Main chỉ nên compose chúng. Khi tạo level mới, bạn có thể instance cùng Player/HUD nhưng thay Items và environment.
Scene inheritance hoặc composition sâu hơn chỉ cần khi prototype lớn lên. Ở giai đoạn đầu, một scene nhỏ có một trách nhiệm rõ ràng thường dễ debug hơn một hierarchy abstraction quá sớm.

Kiểm CollisionShape2D có shape hợp lệ, collision layer/mask của Player và Item có tương tác, monitoring của Area2D có bật và signal body_entered thực sự được kết nối. Bật Visible Collision Shapes khi chạy để quan sát collider thay vì đoán bằng sprite.
Log callback của GameManager, kiểm connection được tạo trước khi Item bị nhặt và kiểm data không null. Nếu Item được spawn động, kết nối signal ngay khi instantiate giúp lifecycle rõ nhất.
Kiểm instance đã được gán đúng ItemData trước khi _ready() hoặc cập nhật sprite sau khi data đổi. Nếu property type không đúng, Inspector có thể không cho gán asset mong muốn.
Đường dẫn kiểu $ScoreLabel phụ thuộc cấu trúc scene. Nếu đổi hierarchy, reference có thể hỏng. Với node quan trọng, dùng unique name hoặc export NodePath/reference theo kiến trúc phù hợp thay vì rải absolute path.
Khi loop nhặt item đã ổn, có thể thêm animation và sound trước khi queue_free, spawn theo timer, nhiều loại pickup, inventory, save data hoặc level transition. Chỉ đưa GameManager thành Autoload khi state thực sự cần tồn tại giữa nhiều scene.
Nếu item có nhiều behavior khác nhau chứ không chỉ khác dữ liệu, lúc đó cân nhắc scene riêng hoặc component/node bổ sung. Resource không nên bị ép chứa logic gameplay phức tạp chỉ để giảm số scene.
.tres.player.picked_up tới GameManager.Scene, Node và Resource giải quyết ba lớp khác nhau nhưng phối hợp rất mạnh: Node tạo behavior nhỏ, Scene đóng gói cấu trúc để instance, Resource tách dữ liệu khỏi logic. Mini game nhặt vật phẩm là bài tập tốt vì nó buộc bạn dùng cả scene tree, Inspector, collision, signals và reusable data trong một loop đơn giản.
Nếu nắm chắc pattern này, bạn có nền tảng tốt để mở rộng sang inventory, enemy data, weapon config, quest pickup hoặc level composition mà không phải dựng lại kiến trúc từ đầu.
Godot Engine Docs – Nodes and Scenes: https://docs.godotengine.org/en/stable/getting_started/step_by_step/nodes_and_scenes.html
Godot Engine Docs – Resources: https://docs.godotengine.org/en/stable/getting_started/step_by_step/resources.html
Godot Engine Docs – Creating instances: https://docs.godotengine.org/en/stable/getting_started/step_by_step/instancing.html
Godot Engine Docs – Signals: https://docs.godotengine.org/en/stable/getting_started/step_by_step/signals.html




Đăng ký miễn phí, lấy link riêng và giới thiệu NextGZ cho người cần học tiếng Trung hoặc Digital Art.
Cộng đồng thực chiến
Tham gia nhóm để nhận tài nguyên, cập nhật công cụ và trao đổi cách xây dựng digital business cùng AI.
Tham gia nhóm ZaloCộng đồng sáng tạo
Kết nối với cộng đồng Digital Art, chia sẻ tác phẩm và học hỏi quy trình sáng tạo mới.
Tham gia DiscordCộng đồng thực chiến
Tham gia nhóm để nhận tài nguyên, cập nhật công cụ và trao đổi cách xây dựng digital business cùng AI.
Tham gia nhóm ZaloCộng đồng sáng tạo
Kết nối với cộng đồng Digital Art, chia sẻ tác phẩm và học hỏi quy trình sáng tạo mới.
Tham gia Discord
Bình luận
0 bình luận
Đăng nhập để tham gia thảo luận cùng cộng đồng!
Đăng nhập ngayĐang tải bình luận...