AchTask
AchTask는 UniTask와 System.Threading.Tasks.Task를 하나의 API로 통합하는 비동기 래퍼입니다.
프로젝트에 UniTask가 설치되어 있으면 자동으로 UniTask를 사용하고, 없으면 Task로 폴백합니다.
설치 감지
com.cysharp.unitask 패키지가 프로젝트에 존재하면 ENABLE_UNITASK 심볼이 자동 정의됩니다.
별도 설정 없이 asmdef의 versionDefines가 감지하므로 코드와 문서를 바꿀 필요가 없습니다.
| 환경 | 내부 구현 |
|---|---|
| UniTask 설치됨 | UniTask / UniTask<T> |
| UniTask 없음 | System.Threading.Tasks.Task / Task<T> |
await 지원
AchTask는 직접 await할 수 있습니다.
await AchTask.Delay(2f);
await AchTask.WaitUntil(() => isReady);
정적 팩토리
Delay / DelayRealtime
// 게임 시간 기준 대기 (UniTask: Time.timeScale 반영 / Task 폴백: 벽시계)
await AchTask.Delay(1.5f);
// 실제 경과 시간 기준 대기 (timeScale 무관)
await AchTask.DelayRealtime(1.5f);
// CancellationToken 지원
var cts = new CancellationTokenSource();
await AchTask.Delay(5f, cts.Token);
주의:
Delay는 UniTask 환경에서Time.timeScale을 반영합니다. 슬로우모션 중에도 실제 시간으로 대기하려면DelayRealtime을 사용하세요.
WaitUntil
// 조건이 참이 될 때까지 대기
await AchTask.WaitUntil(() => player.IsGrounded);
// 취소 가능
await AchTask.WaitUntil(() => dialogueFinished, cts.Token);
WhenAll / WhenAny
var a = AchTask.Delay(1f);
var b = AchTask.Delay(2f);
var c = AchTask.Delay(3f);
// 셋 모두 완료될 때까지
await AchTask.WhenAll(a, b, c);
// 가장 먼저 끝나는 하나가 완료될 때까지
await AchTask.WhenAny(a, b, c);
CompletedTask
// 이미 완료된 태스크 (조건 분기 반환 등에 유용)
return condition ? DoWorkAsync() : AchTask.CompletedTask;
반환값 — AchTask<T>
public static AchTask<string> FetchNameAsync()
{
return AchTask<string>.FromResult("Player");
}
string name = await FetchNameAsync();
암묵적 변환
UniTask 또는 Task와 상호 변환할 수 있습니다.
// UniTask 환경
UniTask uniTask = someAchTask; // AchTask → UniTask
AchTask achTask = someUniTask; // UniTask → AchTask
// Task 폴백 환경
Task task = someAchTask.AsTask(); // AchTask → Task
AchTask from = someTask; // Task → AchTask (암묵적)
전체 예시
// 단순 순차 대기
async AchTask LoadSequenceAsync(CancellationToken ct)
{
await AchTask.Delay(0.5f, ct); // 페이드 인
await AchTask.WaitUntil(() => dataLoaded, ct);
await AchTask.Delay(0.2f, ct); // 전환 여유
}
// 여러 작업 병렬 실행
async AchTask InitAllAsync()
{
await AchTask.WhenAll(
LoadAudioAsync(),
LoadTableAsync(),
LoadUserDataAsync()
);
}
// 먼저 끝나는 쪽으로 분기
async AchTask RaceAsync()
{
await AchTask.WhenAny(
AchTask.Delay(3f), // 타임아웃
AchTask.WaitUntil(() => input) // 유저 입력
);
}