앞서 제작하던 게임에서 스킬을 비동기적으로 처리해야 할 때 Unitask와 CancellationToken을 사용한 적이 있었다.
유니티 비동기 작업 (Unitask, CancellationToken)
몬스터의 스킬 비동기 시전 앞서 제작한 몬스터의 스킬을 Scriptable Object 로 구현할 때, 몬스터의 각 스킬을 정해진 확률에 맞춰 Queue 순서대로 등록시킨 뒤, 해당 스킬을 사용하기 위한 Cost가 충
toacode.tistory.com
이때 Unitask의 사용법과 기능적인 결과는 얼추 알고 있었지만, 정확히 어떤 구조이며 어떤 기능을 하는지 등을 조금 더 알고 싶어서 추가적인 조사를 하였다.
<Unitask 와 Task >는 비동기 프로그래밍으로, 프로그램의 실행 흐름을 비동기적으로 처리하여, 실행 중인 하나의 작업과는 별개로 또 다른 작업을 수행할 수 있도록 하는 프로그래밍 방식이다.
Unitask에 대한 설명에 앞서, Task와 코루틴이라는 대표적인 비동기 프로그래밍을 알아야 하는데,
기본적으로 Task는 async 와 await키워드를, 코루틴은 yield 키워드를 사용하여 비동기적으로 작업을 관리한다.
1.Task
Task의 경우 await을 통해 멀티스레드를 사용하여 CPU 부하가 큰 작업을 분산해서 처리가 가능함으로, 네트워크 요청, 데이터 처리 등의 무거운 독립적인 실행을 처리하는데 적합하며, 단점으로는 Task를 이용해서 Unity의 GameObject나 UI 등을 변경할 수 없다는 점이 있다.
2. 코루틴
반대로 코루틴의 경우에는 메인 스레드를 통해서 실행되며 Unity 엔진이 직접 관리하는 스레드임으로 Unity의 GameObject나 UI 업데이트가 가능하고, 물리 연산 또한 조작가능한 장점이 존재한다.
또한 프레임 단위로 이루어지는 작업에 있어서, 여러 프레임 단위에 걸쳐서 작업의 처리를 원하거나, 한 프레임 단위에서 처리하기에는 너무 많은 작업량을 분산해서 처리할 수 있다.
※ 따라서 간단하게 정리하면 Task의 경우, 무겁고 복잡한 비동기 작업에 특화가 되어있으며, 코루틴의 경우 프레임 단위의 로직이 필요하거나, Unity 객체와 직접 상호작용이 필요한 경우 사용하는 것이 좋다고 볼 수 있다.
Unitask
자 그럼 Unitask는 어떠한 특성이 있을까 알아보자.
Unitask는 유니티에서 비동기 작업을 처리하기 위한 도구로, 코루틴의 기능을 대체하며 Task와 비교하였을 때에도 유니티에서 더 효율적으로 동작하도록 설계되었다고 한다.
또한 Task의 class구조와는 다르게 구조체(struct) 기반으로 메모리의 스택에 할당되어 관리된다. 이는 코루틴과 다르게 힙 할당이 발생하지 않기에 GC의 부하가 줄어들며, 메모리 누수를 방지하기 위한 task tracker 또한 제공하기 때문에 , 결과적으로는 Zero Alloaction과 같은 효과를 볼 수 있다.
(Zero allocation : 메모리 할당 없이 작업을 수행하거나 최소한의 메모리 할당만을 사용하여 높은 성능을 달성하기 위한 기술 또는 방식.)
Unitask는 이름에는 Task가 들어가 있지만 기능적인 면에서는 코루틴과 비슷한 방식으로 적용 가능하며 더 유니티 친화적인 모습이라 볼 수 있다.
하지만 코루틴과 비교하였을 때 무조건 장점만 있는 것은 아닌데, 코루틴은 비동기 작업이 오브젝트가 파괴되면 자동으로 정지되어 따로 조치를 할 필요가 없지만. Unitask의 경우 오브젝트가 파괴되어도 실행될 수 있기에 메모리 누수와 함께 이미 사라진 객체에 접근을 시도할 수 있기 때문에 오류가 발생할 수 있다.
따라서. Unitask는 대상 오브젝트가 파괴 or 비활성화될 수 있는 경우 직접 CancellationToken을 통해 비동기 실행에 대한 정보를 힙에 저장하고, 파괴 or 비활성화 시 힙 영역에 저장된 CancellationToken을 통해 비동기 실행을 취소한다.
★ Unitask는 스택에 저장, 이것의 취소 관리는 힙에 저장
<예시 코드>
async void Start()
{
await UniTask.Delay(5000, cancellationToken: this.GetCancellationTokenOnDestroy());
Debug.Log("이 메시지는 오브젝트가 살아 있을 때만 출력된다.");
}
Unitask의 사용 방법과, 구조, CancellationToken의 선언 방식등은 글 상단의 이전글 링크를 통해서 확인할 수 있다.
아래는 Unitask의 깃허브 주소이다.
https://github.com/Cysharp/UniTask
GitHub - Cysharp/UniTask: Provides an efficient allocation free async/await integration for Unity.
Provides an efficient allocation free async/await integration for Unity. - Cysharp/UniTask
github.com
'C# > 게임 제작 + TIL' 카테고리의 다른 글
Unity Scrolling Background - 무한 배경 (0) | 2025.02.19 |
---|---|
Dotween Pause() (0) | 2025.02.18 |
C# 컬렉션 (FirstOrDefault(); ) (0) | 2025.02.04 |
ConsoleApp 텍스트 RPG (직렬화, 역직렬화 사용중 발생한 오류) (2) | 2025.02.03 |
함수 포인터 (Action , func) (0) | 2025.01.31 |