Giới thiệu chung
Trong lập trình bất đồng bộ, Task và UniTask 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ượngTask
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
YieldInstruction
vàCustomYieldInstruction
: Bạn có thể dễ dàng chờ các loại coroutine của Unity nhưWaitForSeconds
,WaitForEndOfFrame
, hoặcWaitUntil
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
trongMonoBehaviour
.
- 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