Đang tải...

Tôi port game Godot 2D sang Android — đây là những gì làm fps tụt từ 60 xuống 22

07/05/2026
8 phút đọc
Tôi port game Godot 2D sang Android — đây là những gì làm fps tụt từ 60 xuống 22
![Tôi port game Godot 2D sang Android — fps từ 60 xuống 22 và cách sửa](https://i.imgur.com/EOaajf4.png) Tuần trước tôi port một prototype game 2D từ Godot 4.4 desktop sang Androi...

Tôi port game Godot 2D sang Android — fps từ 60 xuống 22 và cách sửa

Tuần trước tôi port một prototype game 2D từ Godot 4.4 desktop sang Android. Trên PC nó chạy mượt 60 fps. Lần build đầu tiên trên một chiếc Pixel 4a tầm trung, fps tụt xuống 22. Game tổng cộng có khoảng 40 sprite trên màn hình, vài shader cơ bản, một particle system, và nhạc nền Ogg.

Bài viết này là log những gì tôi tìm ra khi profile, cộng với các fix thực tế đã làm fps trở lại 60 trên cùng thiết bị. Ai đang nghĩ tới chuyện port Godot game lên mobile thì có thể tham khảo trước khi mất một buổi tối debug như tôi.

Renderer: GLES3 hay Compatibility?

Mặc định Godot 4 dùng renderer Forward+, được tối ưu cho desktop GPU mạnh. Trên mobile, đây gần như luôn là sai lựa chọn cho game 2D.

Vào Project Settings → Rendering → Renderer → Rendering Method, đổi sang Compatibility (renderer dựa trên GLES3, tương thích rộng nhất với GPU mobile). Game 2D của tôi chạy nhanh hơn ngay khoảng 30%.

Nếu bạn build game 3D nặng và muốn dùng Forward Mobile, cần test cả device tầm thấp; một số GPU Mali (đặc biệt G52 trở xuống) chạy khá kém với Vulkan của Godot 4.4.

Tài liệu chính thức: Godot Renderers.

MSAA và viewport scale

Project Settings → Rendering → Anti Aliasing → MSAA 2D: đặt là Disabled cho mobile. MSAA cực đắt trên mobile GPU. Nếu cần khử răng cưa thì dùng 2D > Snap 2D Transforms To Pixel = On cộng với pixel art textures.

Rendering → Viewport → 2D > Snap 2D Transforms To Pixel: bật.

Rendering → Scaling 3D (kể cả game 2D mà có Camera với 3D mode): đặt mode Bilinear thay vì FSR 2.

Một thiết lập tôi đã miss và chỉ phát hiện khi profile: một số texture gốc tôi import ở 4096×4096 cho card art. Trên mobile, max texture size hiệu quả là 2048×2048; trên một số device cũ là 1024×1024. Resize hết về 1024 max → đỡ được khoảng 8 fps nữa.

Texture compression: ETC2/ASTC bắt buộc

Đây là phần tốn nhiều thời gian nhất. Mặc định Godot import texture dưới dạng VRAM uncompressed cho desktop. Trên mobile, mỗi texture không nén ăn RAM gấp 4–8 lần và làm GPU bandwidth chết ngạt.

Vào Project Settings → Rendering → Textures → VRAM Compression:

  • Import ETC2 ASTC = On (bắt buộc cho mobile)
  • Import S3TC BPTC = Off (chỉ desktop dùng)

Xong rồi, vào từng texture trong file system → tab Import → đổi Compress > Mode thành VRAM Compressed. Reimport.

Lần đầu reimport lâu (build texture cache cho ETC2), nhưng sau đó APK của tôi giảm từ 38 MB xuống 14 MB, và fps tăng thêm 5–7. Memory peak giảm gần một nửa.

Cảnh báo: nếu game có pixel art rõ nét, ETC2 lossy có thể làm hỏng viền sprite. Trong trường hợp đó dùng Lossless cho riêng mấy sprite UI/icon, còn background và effect thì để lossy.

Audio: ogg streaming thay vì load toàn bộ

Tôi có 4 file nhạc nền, mỗi file 3–4 phút Ogg Vorbis. Mặc định Godot load nguyên file vào RAM khi AudioStreamOggVorbis.load_from_file(). Trên Pixel 4a, nguyên 4 track ngốn ~80 MB RAM trước khi gameplay bắt đầu.

Fix: vào từng .ogg → tab Import → bật Loop nếu cần, nhưng quan trọng hơn là set Beat Count và đặc biệt Bar Beats chỉ khi cần. Sau đó trong code, đảm bảo bạn dùng AudioStreamPlayer chứ không phải AudioStreamPlayer3D cho nhạc nền (3D có overhead vô ích cho nhạc nền 2D).

Cho SFX ngắn (<1 giây): leave as-is, load vào RAM nhanh hơn streaming. Chỉ stream cho nhạc nền dài. Quy tắc đơn giản: file > 1 MB thì stream.

Particles: GPU vs CPU và max amount

GPUParticles2D trên mobile thực ra không hề "free" như trên desktop. Trên Adreno đời cũ, GPU particles có thể chậm hơn CPU particles vì shader compilation overhead.

Nếu bạn có ít hơn 200 particles cùng lúc, dùng CPUParticles2D. Tôi đổi và performance ổn định hơn nhiều, nhất là trên 60Hz target.

Đặt Amount thực tế: nhiều người (kể cả tôi) để default 8 hoặc tăng lên hàng nghìn "cho chắc". Amount là số particles GPU có thể alloc cùng lúc; đặt cao kể cả không spawn hết vẫn tốn buffer. Đặt sát số bạn thực sự cần.

Vài thứ nhỏ nhưng cộng lại đáng kể

  • Tắt vsync option Adaptive (Project Settings → Display → Window → V-Sync Mode): trên một số device, Adaptive gây microstutter. Set Enabled cho mobile.
  • process_mode của các node không cần update: set PROCESS_MODE_DISABLED khi node không hoạt động (ví dụ enemies off-screen). Godot vẫn duyệt qua scene tree để gọi _process — disabled node skip nhanh hơn.
  • Resolution scaling: trong settings game, cho người chơi chọn render scale 0.75x. Trên thiết bị Android tầm thấp, render ở 0.75 rồi upscale gần như không nhận ra khác biệt với 2D, nhưng tăng fps đáng kể.
  • Build với Export with Debug = Off cho release. Debug build chậm hơn 30–50% và có symbol làm APK to gấp đôi.

Profile tool: Remote Debug + adb logcat

Để biết bottleneck ở đâu, đừng đoán. Build một bản debug, plug Pixel vào máy qua USB, rồi Project → Export → Android → Remote Debug (chọn device đã connect). Đợi vài giây sau khi game chạy, mở Debugger → Profiler trong Godot editor. Bạn sẽ thấy frame time breakdown thật.

Song song, mở terminal:

adb logcat -s godot

Logs từ print() của bạn cùng warnings runtime sẽ hiện ngay. Nếu bạn thấy nhiều dòng WARNING: Texture is too large hoặc Out of GPU memory, đó là dấu hiệu rõ ràng phần nào cần fix.

AI và mobile-specific code

Tôi note thêm phần này vì đáng nói (tôi nói điều này với bias rõ ràng: tôi đang xây dựng Ziva, một AI agent cho Godot). Khi nhờ ChatGPT hay Cursor viết code optimize cho Godot mobile, kết quả thường là code chung cho desktop. Vì training data của model lớn không có nhiều ví dụ Godot 4 mobile cụ thể, AI thường suggest setting Forward+ hoặc bật MSAA 4x — đúng kiểu setting làm chậm đứng trên Android.

Khi tôi build Ziva, ground truth là API XML của Godot và docs chính thức, nên ít nhất AI không bịa ra set_msaa_2d_quality() (function không tồn tại) hay Texture2D.compress_etc2_mobile() mà tôi đã gặp khi hỏi GPT-5 và Claude. Nhưng dù dùng tool nào, nguyên tắc chung: với mobile Godot, đừng tin AI mặc định, luôn check setting trên thiết bị thật.

Kết luận ngắn

Sau khi áp dụng hết: fps trên Pixel 4a đi từ 22 → 58–60 ổn định, RAM peak từ 380 MB xuống 210 MB, APK từ 38 MB xuống 14 MB. Không phải con số khủng khiếp gì, nhưng đủ để game chạy được trên thiết bị tầm trung VN, vốn là phần lớn user base nếu bạn release ở Việt Nam.

Nếu bạn đang port một game nhỏ sang Android và bị tụt fps, hãy bắt đầu bằng đổi renderer sang Compatibility, bật ETC2 compression, và disable MSAA. Ba thứ đó đã giải quyết khoảng 70% vấn đề trong case của tôi.

📚 Nguồn: Viblo

Chia sẻ bài viết

Cần tư vấn?

Liên hệ với chúng tôi để được hỗ trợ

Liên hệ ngay

Bài viết liên quan

Simple Jewelry Styles That Never Feel Overdone
07/05/2026

Simple Jewelry Styles That Never Feel Overdone

Jewelry trends continue to change every season, yet many people still return to simple designs that feel comfortable, wearable, and easy to match with daily outfits. Clean lines, balanced settings, an...

Đọc thêm
Xây dựng Quản lý kho hàng (Listing Management) trong hệ thống Bất Động Sản
07/05/2026

Xây dựng Quản lý kho hàng (Listing Management) trong hệ thống Bất Động Sản

Trong ngành Bất động sản (Proptech), việc quản lý kho hàng (Listing Management) không đơn giản là CRUD mà là bài toán về Tính nhất quán dữ liệu và Quản lý trạng...

Đọc thêm
PHP Class Type Hinting: Đừng để Code của bạn chạy bằng "Hệ tâm linh"
07/05/2026

PHP Class Type Hinting: Đừng để Code của bạn chạy bằng "Hệ tâm linh"

### 1. Mở đầu: Câu chuyện về những bug "trên trời rơi xuống" Hẳn là ai trong chúng ta cũng từng trải qua cảm giác này: Nhận một dự án cũ (legacy code), mở mộ...

Đọc thêm

Bắt đầu dự án của bạn

Hãy để Flash Dev đồng hành cùng bạn

Liên hệ ngay