유니티에서 사용하는 비동기에 대해 알아보자.
유니티에서는 비동기 수행하는데 있어서 크게 2가지로 나뉜다.
하나는 Coroutine, 하나는 Async/Await 이다.
Coroutine은 유니티의 메인 스레드에서 동작하며, yield return으로 비동기 흐름을 표현는 것으로 실질적으로 비동기 형태로 실행되진 않는다.
Async/Await은 C# 언어 자체 기능으로, 실제 비동기 작업(다른 스레드) 또는 비동기 I/O를 처리가 가능하다.
크게 두가지의 차이점으로는
Coroutine은 유니티 프레임워크에 종속적이며 Update 루프에서 스케줄링하게 된다.
Async/Await는 .NET/C#의 표준 비동기 방식으로, CPU 바운드/IO 바운드 작업 모두 처리 가능.
하지만 유니티에서는 Async/Await 을 사용하게 되면 Unity API 대부분은 메인 스레드에서만 안전하게 호출 가능. Async 스레드에서 UI 조작 시 문제가 생길 수 있으므로, 적절한 스레드 전환이 필요하다.
예를 들어
같은 문제가 있다.
그런데 Unity6로 넘어가면서 Awaitable 이라는 녀석이 생겼는데 Awaitable 타입은 유니티에서 Task를 대체하여 비동기 작업을 표현하는 타입으로, 유니티가 추적할 수 있는 타입으로 Awaitable은 Task와 비교하여 유니티 개발 환경에 최적화되어 설계되어 나오게 된 것이다.
이로써 유니티에서 온전히 async/await을 사용 할 수 있게 되었다.
예시 코드
public async Awaitable GetAssetAsync(string assetName)
{
var assetLoadOperation = Addressables.LoadAssetAsync(assetName);
await assetLoadOperation.Task;
return loadedAsset = assetLoadOperation.Result;
}
public async void Start()
{
var loadedAsset = await GetAssetRoutine("boat");
await DoSomethingAsync1(loadedAsset);
await DoSomethingAsync2(loadedAsset);
await DoSomethingAsync3(loadedAsset);
}
(콜백 지옥 안녕..)
아무래도 Awatiable 풀링해서 사용하다보니 상황에 따라 다른 Awatiable 을 사용해야하지만 동일한 Awatiable 인스턴스를 사용하는 경우가 있나보다.
자세한 내용은 참조 페이지를 보면 되겠다.
(참조: https://www.unitysquare.co.kr/growwith/unityblog/webinarView?id=566)
얼른 Unity6로 넘어가야지..