Sử dụng Tween trong Godot 4 để tạo animation mượt mà bằng code
Tween là một trong những công cụ hữu dụng nhất trong Godot 4 nhưng cũng bị bỏ qua nhiều nhất. Nếu bạn từng viết animation bằng _process(delta) và tính toán lerp() thủ công, Tween có thể thay thế 20 dòng code đó bằng 1 dòng.
Bài viết này hướng dẫn cách dùng Tween trong Godot 4 với code thực tế, có thể copy chạy được ngay.
Tween là gì?
Tween (tweening) là kỹ thuật biến đổi một giá trị từ A sang B theo thời gian, kèm theo các hàm easing (ease-in, ease-out, bounce, elastic). Trong Godot 4, Tween là một class — không phải một node nữa như Godot 3.x.
Bạn không thêm Tween vào scene tree. Bạn tạo Tween bằng code:
var tween = create_tween()
Mỗi Tween là một sequence độc lập. Khi sequence kết thúc, Tween tự động bị giải phóng.
Ví dụ cơ bản: di chuyển sprite
Di chuyển một Sprite2D từ vị trí hiện tại sang (500, 300) trong 1 giây:
extends Sprite2D
func _ready():
var tween = create_tween()
tween.tween_property(self, "position", Vector2(500, 300), 1.0)
3 dòng code. Không cần _process(). Không cần tính delta. Khi tween kết thúc, sprite ở đúng vị trí đích.
Easing và Transition
Tween có 11 transition type và 4 easing direction. Mặc định là LINEAR + EASE_IN_OUT.
var tween = create_tween()
tween.set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT)
tween.tween_property(self, "position", Vector2(500, 300), 1.0)
TRANS_BACK + EASE_OUT tạo hiệu ứng "lùi rồi đẩy" — sprite hơi lùi lại trước khi lao đến đích. Hữu ích cho hiệu ứng UI khi popup xuất hiện.
Các transition type phổ biến:
TRANS_LINEAR— không có easingTRANS_CUBIC— mượt mà, phù hợp cho chuyển động vật lýTRANS_BACK— overshoot, popup/dialogTRANS_ELASTIC— đàn hồi, hiệu ứng "wobble"TRANS_BOUNCE— như bóng nảy
Chaining: nối nhiều animation
Đây là lý do chính khiến tôi yêu Tween. Nối nhiều bước animation thành một sequence:
func attack_animation():
var tween = create_tween()
tween.tween_property(self, "position:x", position.x - 30, 0.1)
tween.tween_property(self, "position:x", position.x + 50, 0.2)
tween.tween_property(self, "position:x", position.x, 0.15)
Đây là hiệu ứng "wind-up + attack + recovery" trong 3 dòng code. Tween chạy lần lượt: lùi 30 pixel trong 0.1s, lao tới 50 pixel trong 0.2s, quay về 0.15s.
Lưu ý cú pháp "position:x" — bạn có thể animate chỉ một thành phần của một property phức tạp.
Parallel: chạy song song
Nếu muốn animate position và scale cùng lúc:
func pop_in():
var tween = create_tween().set_parallel(true)
tween.tween_property(self, "scale", Vector2(1, 1), 0.3) \
.from(Vector2.ZERO).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT)
tween.tween_property(self, "modulate:a", 1.0, 0.3) \
.from(0.0)
set_parallel(true) đặt tất cả các tween trong sequence chạy song song. from() đặt giá trị bắt đầu. Kết hợp lại tạo hiệu ứng "fade in + zoom" cho UI.
Callback: gọi hàm khi tween kết thúc
func play_death():
var tween = create_tween()
tween.tween_property(self, "modulate:a", 0.0, 0.5)
tween.tween_callback(queue_free)
tween_callback gọi một hàm khi đến lượt của nó trong sequence. Ở đây sprite fade out trong 0.5 giây, rồi tự gọi queue_free().
Lưu ý: callback nhận một Callable, không phải string. Đừng viết tween_callback("queue_free") — Godot 3 syntax cũ.
Lỗi thường gặp
-
Quên
create_tween()trong loop: nếu bạn gọicreate_tween()trong_process(), mỗi frame tạo một Tween mới. Sau 1 giây bạn có 60 Tween đang chạy đè lên nhau. Kiểm tra trước khi tạo:if not tween or not tween.is_running(). -
Animate node đã free: nếu node bị
queue_free()giữa chừng tween, game sẽ crash. Lưu reference cẩn thận. -
Dùng "position:x" với CharacterBody2D:
CharacterBody2Ddùngvelocityvàmove_and_slide(). Tween trực tiếppositionsẽ bỏ qua collision. DùngAnimationPlayercho character motion. -
Quên
set_loops()khi muốn lặp: muốn loop vô hạn?tween.set_loops(0). Loop 3 lần?set_loops(3).
So sánh với AnimationPlayer
Tween và AnimationPlayer đều làm animation, nhưng dùng trong tình huống khác nhau:
- Tween: animation đơn giản, sinh ra bằng code, một lần dùng. Reusable patterns như "fade out + free", "pop-in UI", "shake".
- AnimationPlayer: animation phức tạp, có nhiều keyframe, cần preview trong editor. Character animation, cinematics.
Quy tắc: dùng Tween khi animation < 5 keyframe và sinh ra bằng code. Dùng AnimationPlayer khi cần edit visually.
AI thường viết Tween Godot 3 cũ
Khi bạn hỏi ChatGPT "viết tween cho Godot", thường nhận được code dùng Tween như một node con với interpolate_property() và start() — đây là API Godot 3, không hoạt động trong Godot 4. Godot 4 dùng create_tween() và tween_property().
Ziva là một AI agent chạy bên trong editor Godot. Vì biết phiên bản Godot thực tế của project, nó dùng đúng API Godot 4 ngay từ đầu — không phải đoán từ training data.
Kết luận
Tween là công cụ animation gọn nhẹ và mạnh mẽ trong Godot 4. Học tween_property, easing, chaining, và parallel là đủ để cover 80% các trường hợp animation trong game. Khi cần animation phức tạp hơn, chuyển sang AnimationPlayer.
Hãy thử áp dụng Tween cho các hiệu ứng UI nhỏ trong game của bạn trước — pop-in dialog, fade-in label, shake button. Chỉ cần vài dòng code là code base bớt rối ngay.
All rights reserved