Tối ưu game Unity cho điện thoại: những việc làm ngay để chạy mượt hơn

  • author-image

    Nguyễn Đình Cường

  • blog-tag
  • blog-comment 0 comment
  • created-date 09 Nov, 2026
blog-thumbnail

Một trò chơi chạy mượt trên máy tính có thể giật mạnh trên điện thoại tầm trung. Thiết bị di động có giới hạn về CPU, GPU, bộ nhớ và nhiệt độ. Bài viết tổng hợp các kỹ thuật tối ưu Unity quan trọng nhất cho game di động.

Luôn bắt đầu bằng Profiler

Đừng tối ưu theo cảm tính. Unity Profiler cho biết thời gian CPU, GPU, bộ nhớ và bộ thu gom rác. Hãy kết nối trực tiếp với thiết bị thật và thử trên máy cấu hình thấp mà bạn muốn hỗ trợ. Xác định xem trò chơi bị giới hạn bởi CPU hay GPU rồi mới chọn hướng xử lý.

Giảm draw call

Mỗi lần CPU yêu cầu GPU vẽ một nhóm đối tượng gọi là draw call, và quá nhiều sẽ gây nghẽn.

  • Dùng chung vật liệu giữa các đối tượng để Unity gộp được.
  • Gộp nhiều ảnh nhỏ thành một Sprite Atlas cho trò chơi 2D và giao diện.
  • Dùng static batching cho vật thể đứng yên và GPU instancing cho nhiều bản sao cùng mô hình.
  • Hạn chế số lượng đèn thời gian thực; ưu tiên ánh sáng nướng sẵn (baked) khi phù hợp.

Tránh cấp phát bộ nhớ mỗi khung hình

Tạo đối tượng liên tục sinh rác, dẫn đến đợt thu gom rác gây khựng bất chợt. Dùng object pooling để tái sử dụng thay vì liên tục Instantiate và Destroy:

using System.Collections.Generic;
using UnityEngine;

public class BulletPool : MonoBehaviour
{
    [SerializeField] private GameObject bulletPrefab;
    [SerializeField] private int initialSize = 20;
    private readonly Queue<GameObject> pool = new Queue<GameObject>();

    void Awake()
    {
        for (int i = 0; i < initialSize; i++)
        {
            var b = Instantiate(bulletPrefab, transform);
            b.SetActive(false);
            pool.Enqueue(b);
        }
    }

    public GameObject Get(Vector3 position)
    {
        var b = pool.Count > 0 ? pool.Dequeue() : Instantiate(bulletPrefab, transform);
        b.transform.position = position;
        b.SetActive(true);
        return b;
    }

    public void Return(GameObject b)
    {
        b.SetActive(false);
        pool.Enqueue(b);
    }
}

Viết Update gọn nhẹ

  • Lưu tham chiếu thành phần trong Awake hoặc Start thay vì gọi GetComponent mỗi khung hình.
  • Tránh dùng Find, FindObjectOfType trong Update.
  • Không nối chuỗi liên tục hoặc dùng LINQ nặng trong vòng lặp nóng.
  • Giảm tần suất việc không cần chạy mỗi khung hình bằng bộ đếm thời gian hoặc coroutine.
  • So sánh thẻ bằng CompareTag thay vì so sánh chuỗi.
private Rigidbody2D rb;

void Awake()
{
    rb = GetComponent<Rigidbody2D>(); // lấy một lần
}

void FixedUpdate()
{
    rb.velocity = new Vector2(speed, rb.velocity.y);
}

Texture và bộ nhớ

  1. Dùng định dạng nén phù hợp thiết bị di động (như ASTC) và kích thước hợp lý; không dùng texture 4K cho vật nhỏ.
  2. Tắt Read/Write Enabled nếu không cần truy cập từ code.
  3. Giải phóng tài nguyên không dùng khi chuyển cảnh.
  4. Dùng Addressables để tải tài nguyên theo nhu cầu và giảm bộ nhớ.

Vật lý, hiệu ứng và giao diện

  • Giảm số collider phức tạp; dùng collider đơn giản như hình hộp hoặc hình tròn.
  • Thiết lập ma trận va chạm layer để bỏ qua kiểm tra không cần thiết.
  • Hạn chế hệ thống hạt có số lượng lớn và hiệu ứng hậu kỳ nặng.
  • Giao diện Canvas: tách phần tĩnh và phần động sang Canvas khác nhau, vì thay đổi một phần tử có thể buộc dựng lại cả Canvas.

Tốc độ khung hình và nhiệt độ

Điện thoại sẽ giảm xung nhịp khi nóng, làm trò chơi tụt hiệu năng sau vài phút. Đặt tốc độ khung hình mục tiêu hợp lý, ví dụ 30 hoặc 60 tùy loại trò chơi, thay vì để chạy tối đa không cần thiết. Việc này tiết kiệm cả pin.

void Start()
{
    Application.targetFrameRate = 60;
    QualitySettings.vSyncCount = 0;
}

Cài đặt xây dựng

Chọn backend IL2CPP và kiến trúc ARM64 cho bản phát hành Android để có hiệu năng tốt và đáp ứng yêu cầu của cửa hàng. Bật nén và loại bỏ mã không dùng (stripping) để giảm dung lượng, rồi kiểm thử kỹ.

Kết luận

Quy trình hiệu quả là đo bằng Profiler trên thiết bị thật, xử lý điểm nghẽn lớn nhất, đo lại. Giảm draw call, dùng pooling, tránh cấp phát mỗi khung hình và nén texture đúng cách đã giải quyết phần lớn vấn đề hiệu năng.

Thử trên nhiều thiết bị và theo dõi nhiệt độ

Đừng chỉ thử trên máy mạnh của bạn. Hãy chuẩn bị ít nhất một máy cấu hình thấp và một máy tầm trung để đại diện. Chơi liên tục khoảng nửa tiếng để xem hiệu năng có tụt khi máy nóng không. Cho phép người chơi chọn mức chất lượng đồ họa, và đặt giá trị mặc định theo cấu hình phát hiện được. Cách này giúp trò chơi chạy được trên nhiều loại máy mà không phải hy sinh trải nghiệm cho người dùng máy mạnh.

Nếu bạn muốn học làm game Unity từ cơ bản đến phát hành trên di động, hãy xem các khóa học tại codebem.com.

author_photo
Nguyễn Đình Cường

0 comment