[Unity] UniTask의 사용법에 관하여
개요
UniTask는 유니티에서 비동기 프로그래밍을 간소화하고 성능을 향상시키기 위해 만들어진 라이브러리입니다. C#의 async
와 await
키워드를 기반으로 작동하며, 유니티의 코루틴보다 훨씬 적은 오버헤드로 비동기 작업을 처리할 수 있도록 설계되었습니다. 마치 택배 관리 시스템에서 여러 택배의 정보를 효율적으로 관리하고 추적하는 것과 같습니다.
UniTask는 실제 현장에서 가장 많이 쓰이는것중 하나이기 때문에 반드시 익혀두시는게 좋습니다.
특징
-
가벼운 오버헤드: 유니티의 코루틴보다 훨씬 적은 오버헤드로 비동기 작업을 처리하여 성능 향상에 도움을 줍니다. 마치 택배 관리 시스템이 불필요한 절차를 최소화하여 운영 비용을 줄이는 것과 같습니다.
-
async와 await 지원: C#의 async와 await 키워드를 사용하여 비동기 코드를 동기 코드처럼 쉽게 작성할 수 있습니다. 마치 택배 관리 시스템에서 직관적인 인터페이스를 제공하여 누구나 쉽게 사용할 수 있는 것과 같습니다.
-
다양한 유니티 API 통합: 유니티의 다양한 API (예: WaitForSeconds, WWW, AssetBundle 로딩 등)를 UniTask로 쉽게 변환할 수 있습니다. 마치 택배 관리 시스템이 다양한 택배 회사와 연동되어 정보를 통합 관리하는 것과 같습니다.
-
취소(Cancellation) 지원: 비동기 작업을 취소할 수 있는 기능을 제공하여 리소스 낭비를 방지합니다. 마치 택배 배송을 중간에 취소할 수 있는 것과 같습니다.
-
값 반환: 비동기 작업의 결과를 쉽게 반환받을 수 있습니다. 마치 택배 배송 완료 후 수령 확인을 받는 것과 같습니다.
-
예외 처리: 비동기 작업에서 발생한 예외를 쉽게 처리할 수 있습니다. 마치 택배 배송 중 발생한 문제(예: 파손, 분실)에 대한 처리 절차를 갖추고 있는 것과 같습니다.
코루틴과의 비교
코루틴의 경우 IEnumerator객체를 생성하고 이 객체는 Heap메모리에 할당됩니다. 즉, 가비지컬렉터(GC)의 부하가 커집니다. 뿐만 아니라 코루틴이 일시중지 될 때마다 현재 상태를 저장하기 위한 추가적인 메모리 오버헤드가 발생할 수 있습니다.
반면, UniTask의 경우 기본적으로 Struct 기반으로 구현되기 때문에 Heap이 아닌Stack메모리에 할당되어 GC의 부하가 적습니다. 이로 인해 Zero Allocation효과를 받을 수 있습니다.
Zero Allocation이란?
메모리 할당을 최소화하거나 완전히 없애는 프로그래밍 기법
가비지 컬렉션(GC)의 부하를 줄여 성능을 향상시키는 것이 목적
용도에 맞게 사용하는것이 중요!
- 간단한 작업, 빈도가 낮은 경우: 간단한 시간 지연이나 한 번만 실행되는 비동기 작업에는 코루틴을 사용해도 충분합니다. 마치 가끔씩 편지를 보내는 경우 일반 우편을 이용하는 것과 같습니다.
- 빈번한 작업, 높은 성능 요구, 많은 수의 동시 작업, 정밀한 제어가 필요한 경우: UniTask를 사용하는 것이 좋습니다. 특히, 게임 로직, 네트워크 통신, UI 업데이트 등 성능이 중요한 부분에서 효과적입니다. 마치 중요한 서류나 긴급한 물건을 보낼 때 특송을 이용하는 것과 같습니다.
장단점
장점
- 비동기 코드를 간결하고 가독성 높게 작성할 수 있습니다. 마치 깔끔하게 정리된 택배 관리 시스템의 정보와 같습니다.
- 유니티 코루틴보다 성능이 우수합니다. 마치 더 빠르고 효율적인 택배 배송 시스템과 같습니다.
- 취소 기능을 통해 리소스를 효율적으로 관리할 수 있습니다. 마치 불필요한 배송을 취소하여 비용을 절감하는 것과 같습니다.
단점
- async와 await에 대한 이해가 필요합니다. 마치 택배 관리 시스템의 사용법을 익혀야 하는 것과 같습니다.
- UniTask에 특화된 몇 가지 규칙들을 익혀야 합니다. 마치 택배 관리 시스템의 특별한 용어와 절차를 익혀야 하는 것과 같습니다.
주의점
- 네임스페이스 추가: UniTask 함수를 사용하기 전에
using Cysharp.Threading.Tasks;
네임스페이스를 추가해야 합니다. - async 메서드의 반환 타입:
async
메서드는 Task 또는 UniTask를 반환해야 합니다. 유니티에서는 성능상의 이점 때문에 UniTask를 사용하는 것이 권장됩니다. 마치 택배 관리 시스템에서 택배 정보를 특정 형식으로 관리하는 것과 같습니다. - await 사용: 비동기 작업의 결과를 기다릴 때는
await
키워드를 사용해야 합니다. 마치 택배 배송 완료를 기다리는 것과 같습니다. - 취소 토큰 사용: 비동기 작업을 취소해야 하는 경우,
CancellationToken
을 사용하여 취소 요청을 전달해야 합니다. 마치 택배 배송 취소 요청서를 제출하는 것과 같습니다.
사용법
- UniTask 설치: 유니티 에셋 스토어 또는 Package Manager를 통해 UniTask를 설치합니다.
- 네임스페이스 추가: 스크립트 상단에
using Cysharp.Threading.Tasks;
를 추가합니다. - 비동기 메서드 작성: async 키워드를 사용하여 비동기 메서드를 작성하고, 비동기 작업 결과를 기다릴 때는
await
키워드를 사용합니다. 마치 택배 정보를 입력하고 배송 상황을 확인하는 것과 같습니다.
[WaitForSeconds를 UniTask로 변환]
// 코루틴 방식
IEnumerator MyCoroutine() {
yield return new WaitForSeconds(1f);
Debug.Log("1 second elapsed (Coroutine)");
}
// UniTask 방식
async UniTask MyAsyncMethod() {
await UniTask.Delay(TimeSpan.FromSeconds(1f));
Debug.Log("1 second elapsed (UniTask)");
}
// 사용 예시
void Start() {
StartCoroutine(MyCoroutine());
MyAsyncMethod().Forget(); // UniTask는 Forget()으로 실행해야 함
}
[WWW 요청을 UniTask로 변환]
async UniTask DownloadText() {
using (var www = new UnityWebRequest("https://www.example.com")) {
www.downloadHandler = new DownloadHandlerBuffer();
await www.SendWebRequest().ToUniTask();
if (www.result == UnityWebRequest.Result.Success) {
Debug.Log(www.downloadHandler.text);
} else {
Debug.LogError(www.error);
}
}
}
[CancellationToken 사용]
private CancellationTokenSource cts;
async UniTask MyCancellableMethod() {
cts = new CancellationTokenSource();
try {
await UniTask.Delay(TimeSpan.FromSeconds(5f), cancellationToken: cts.Token);
Debug.Log("Task completed.");
} catch (OperationCanceledException) {
Debug.Log("Task cancelled.");
}
}
void Start() {
MyCancellableMethod().Forget();
}
void Update() {
if (Input.GetKeyDown(KeyCode.Space)) {
cts.Cancel(); // 스페이스 키를 누르면 작업 취소
}
}