Tại Sao Nên Dùng UniTask Thay Task Trong Unity?

4 min read

Giới thiệu chung

Trong lập trình bất đồng bộ, TaskUniTask là hai công cụ phổ biến giúp xử lý các tác vụ mà không làm gián đoạn luồng chính.

Task: Là một cấu trúc thuộc .NET, dùng để quản lý các tác vụ bất đồng bộ với sự hỗ trợ mạnh mẽ từ async/await. Task thích hợp trong các ứng dụng .NET thông thường như web, desktop hoặc xử lý song song.

async Task<int> AddNumbersAsync(int a, int b)
{
    return await Task.Run(() => a + b);
}

UniTask: Là một thư viện tối ưu hóa cho Unity, được thiết kế để thay thế Task. UniTask giúp cải thiện hiệu suất, giảm thiểu phân bổ bộ nhớ và tích hợp tốt với các API đặc thù của Unity như WaitForSeconds hoặc Coroutine

async UniTask WaitAndDo()
{
    await UniTask.Delay(1000); // Chờ 1 giây
    ///Thực hiện các việc cần làm
}

Lý do dùng UniTask thay cho Task trong Unity

Cả hai đều hỗ trợ lập trình bất đồng bộ, nhưng UniTask được đánh giá cao hơn khi làm việc trong Unity vì nhiều lý do cụ thể:

1. Hiệu suất tối ưu hơn

  • Task: Được thiết kế cho các ứng dụng .NET thông thường, Task thường tạo ra đối tượng Task trong bộ nhớ, dẫn đến chi phí phân bổ (allocation) cao. Điều này có thể gây ra vấn đề khi có nhiều tác vụ nhỏ chạy liên tục trong một khung hình (frame).
  • UniTask: UniTask sử dụng cấu trúc dữ liệu không phân bổ (zero-allocation), tránh việc tạo đối tượng không cần thiết trong bộ nhớ heap. Điều này giúp giảm thiểu tải trọng của Garbage Collector (GC), dẫn đến hiệu suất tốt hơn và ít giật lag hơn.

2. Tích hợp tốt hơn với Unity

UniTask được thiết kế chuyên biệt cho Unity và hỗ trợ các hệ thống đặc trưng như:

  • Await cho YieldInstructionCustomYieldInstruction: Bạn có thể dễ dàng chờ các loại coroutine của Unity như WaitForSeconds, WaitForEndOfFrame, hoặc WaitUntil bằng cách sử dụng UniTask.
await UniTask.Delay(2000);

// requires MonoBehaviour(CoroutineRunner))
await UniTask.WaitForEndOfFrame(this); // this is MonoBehaviour

// replacement of yield return new WaitForFixedUpdate()
await UniTask.WaitForFixedUpdate();  

// replacement of yield return WaitUntil
await UniTask.WaitUntil(() => isActive == false);
  • Hỗ trợ Main Thread: UniTask cung cấp các phương thức tiện lợi như UniTask.SwitchToMainThread() để đảm bảo rằng các tác vụ được thực thi trên Main Thread, điều rất quan trọng khi làm việc với API của Unity (vì chúng không an toàn khi gọi từ luồng phụ).

3. Tích hợp tốt hơn với Unity

  • Task cần khởi tạo các đối tượng và cơ sở hạ tầng cần thiết trước khi thực hiện, điều này làm tăng thời gian khởi chạy của tác vụ.
  • UniTask sử dụng cấu trúc dữ liệu đơn giản hơn, giúp khởi tạo nhanh hơn, đặc biệt là với các tác vụ nhỏ hoặc được gọi thường xuyên.

4. Khả năng tương thích cao với API Unity

UniTask hỗ trợ sẵn việc tích hợp với các API Unity như:

  • async/await trong MonoBehaviour.
  • Hỗ trợ tốt hơn với Update, LateUpdate, và các vòng đời khác của Unity
async UniTask<Sprite> LoadAsSprite(string path)
{
    var resource = await Resources.LoadAsync<Sprite>(path);
    return (resource as Sprite);
}

5. Khả năng kiểm soát tốt hơn

UniTask cung cấp các công cụ kiểm soát bổ sung như:

  • CancellationToken: Dễ dàng hủy bỏ tác vụ bất đồng bộ mà không gây rò rỉ bộ nhớ.
  • Timeout: Hỗ trợ thêm thời gian chờ cho một tác vụ.
  • Lựa chọn vòng lặp của Unity (PlayerLoopTiming): Giúp kiểm soát thời điểm tác vụ được thực thi trong các vòng lặp của Unity.
// this CancellationToken lifecycle is same as GameObject.
await UniTask.DelayFrame(1000, cancellationToken: this.GetCancellationTokenOnDestroy());

6. Đơn giản hóa Coroutine

UniTask có thể thay thế hoàn toàn Coroutine trong Unity. Với UniTask, bạn có thể viết code bất đồng bộ theo cách tuyến tính, dễ đọc hơn so với cách tiếp cận Coroutine. Ví dụ so sánh:

Coroutine truyền thống:

IEnumerator MyCoroutine()
{
    yield return new WaitForSeconds(1);
    Debug.Log("Hoàn thành");
}

// Gọi Hàm
StartCoroutine(MyCoroutine());

UniTask:

async UniTask MyAsyncFunction()
{
    await UniTask.Delay(1000);
    Debug.Log("Hoàn thành");
}
// Gọi Hàm
MyAsyncFunction();

7. Hỗ trợ tốt hơn trong game đa nền tảng

UniTask được tối ưu hóa cho các nền tảng sử dụng Unity như:

  • Mobile (iOS/Android).
  • WebGL (nơi yêu cầu giảm thiểu phân bổ bộ nhớ).
  • Console, VR/AR.

Kết Luận

UniTask là một lựa chọn tối ưu cho Unity nhờ hiệu suất cao, khả năng tích hợp tốt với hệ thống Unity, và khả năng kiểm soát linh hoạt. Mặc dù Task có thể phù hợp với các ứng dụng ngoài Unity, UniTask được thiết kế chuyên biệt cho game engine này và nên được ưu tiên sử dụng để tối ưu hóa trải nghiệm phát triển và hiệu năng ứng dụng.

Link tải package: https://github.com/Cysharp/UniTask

Avatar photo

Unity IAP: Triển khai Mua Hàng Consumable

Giới Thiệu Việc tích hợp tính năng mua hàng trong ứng dụng Unity là không thể tránh khỏi. Mua hàng trong ứng dụng có...
Avatar photo Tam Canh Le Chi
6 min read

Leave a Reply

Your email address will not be published. Required fields are marked *