Ngân sách hiệu năng mobile
Assets/
Scripts/
Settings/
thiết lập dự án
đã có sẵnbài này thêm
Bạn đã đạt mức batch và tam giác cho Arena ở tab 04 rồi — nhưng là trên máy bàn. Điện thoại tầm trung chỉ có khoảng một phần mười sức GPU đó, lại còn tự hạ xung khi nóng lên, sau chừng năm phút.
Bốn con số cần giảm, một con số cần tăng.
Ngân sách cho mobile
Draw call / batch: dưới 100 là thoải mái, dưới 60 là an toàn với máy yếu.
Số tam giác trên màn hình: 100k–300k. Cao hơn là GPU tầm trung bắt đầu đuối.
Đèn thời gian thực: một cái directional, chấm hết. Còn lại bake sẵn.
Bộ nhớ texture: dưới 200 MB. Kiểm tra ở module Memory của Profiler, đừng đoán.
Mục tiêu: 60 FPS ổn định, hoặc 30 thật chắc nếu máy không giữ nổi 60.
1. Thiết lập URP — chỗ được lợi nhiều nhất
- 1
Tìm URP Asset của bạn ( cho biết cái nào đang dùng).
- 2
Shadows → Max Distance 40, Cascade Count 1, Shadow Resolution 1024.
- 3
Bỏ tick HDR và bỏ tick MSAA trong URP asset cho mobile. Cả hai đều đắt trên GPU mobile kiểu tile.
- 4
Đặt Render Scale 0.8 trên máy yếu — giảm 20% độ phân giải gần như không thấy được mà tăng tốc rất nhiều.
- 5
Giữ URP asset riêng cho từng mức chất lượng: Mobile Low, Mobile High, Desktop.
2. Texture — thường chiếm nửa dung lượng bản build
- 1
Chọn tất cả texture, đặt Max Size 1024 (512 cho vật phụ, 2048 chỉ dành cho vật chính).
- 2
Compression Format → ASTC 6x6 cho Android. Đó là chuẩn hiện đại, cùng dung lượng mà đẹp hơn ETC2 nhiều.
- 3
Bỏ tick Read/Write Enabled trừ khi bạn thật sự đọc điểm ảnh trong code — nó nhân đôi bộ nhớ.
- 4
Tắt mipmap cho sprite UI; bật cho mọi thứ nằm trong không gian 3D.
3. Script — những lỗi làm mất khung hình
void Update()
{
//quét cả cảnh, 60 lần mỗi giây
GameObject player = GameObject.Find("Player");
//cấp phát đối tượng mới mỗi khung hình
Enemy[] all = FindObjectsOfType<Enemy>();
//tạo chuỗi mỗi khung hình, rác sinh liên tục
label.text = "Score: " + score;
//tra component mỗi khung hình
GetComponent<Rigidbody>().AddForce(Vector3.up);
}private Transform player;
private Rigidbody rb;
private int lastScore = -1;
void Awake()
{
player = GameObject.FindWithTag("Player").transform; // một lần duy nhất
rb = GetComponent<Rigidbody>();
}
void Update()
{
rb.AddForce(Vector3.up);
if (score != lastScore) // chỉ tạo chuỗi khi giá trị thay đổi
{
label.text = "Score: " + score;
lastScore = score;
}
}Bộ dọn rác là thủ phạm gây khựng định kỳ vài giây một lần trên mobile. Gần như toàn bộ đến từ chuỗi và cấp phát mới trong Update.
Thứ gì không cần chạy 60 lần mỗi giây thì cho chạy theo bộ đếm — kiểm tra AI địch mỗi 0.2 giây rẻ hơn 12 lần.
Hàm Update() rỗng vẫn tốn một lần gọi từ engine. Xoá đi.
4. Nhận diện máy rồi hạ cấu hình
using UnityEngine;
public class QualityAutoSetter : MonoBehaviour
{
void Awake()
{
int ram = SystemInfo.systemMemorySize; // tính bằng MB
int cores = SystemInfo.processorCount;
if (ram < 3000 || cores <= 4)
{
QualitySettings.SetQualityLevel(0, true); // Mobile Low
Application.targetFrameRate = 30;
}
else if (ram < 6000)
{
QualitySettings.SetQualityLevel(1, true); // Mobile Medium
Application.targetFrameRate = 60;
}
else
{
QualitySettings.SetQualityLevel(2, true); // Mobile High
Application.targetFrameRate = 60;
}
Debug.Log($"Device: {SystemInfo.deviceModel}, RAM {ram}MB, quality {QualitySettings.GetQualityLevel()}");
}
}Đo trên máy thật, không đo trong editor
Editor chạy trên CPU máy bàn của bạn. Số liệu của nó không nói lên điều gì về điện thoại.
Tick Development Build và Autoconnect Profiler trong Build Profiles, rồi build lên máy và mở Profiler.
Chơi đủ năm phút. Máy nóng thì phút thứ năm chậm hơn phút đầu 20–30% — đó mới là con số cần quan tâm.