UniTask란?
UniTask는 유니티 환경에 특화된 경량 비동기 라이브러리입니다. Task와 비슷한 기능을 제공하면서도 유니티 게임 개발에 적합한 최적화와 기능을 포함하고 있습니다. 특히 다음과 같은 장점을 가지고 있습니다:
- 메모리 할당 최소화: Task는 비동기 작업을 수행할 때 메모리를 많이 사용하지만, UniTask는 GC(가비지 컬렉션) 부담을 줄여줍니다.
- 유니티 API 제공: await UniTask.Delay()나 await UniTask.NextFrame()처럼 유니티 개발에 특화된 메서드를 지원합니다.
UniTask의 기본 사용법
UniTask를 사용하려면 UniTask GitHub에서 패키지를 설치해야 합니다.
https://github.com/Cysharp/UniTask#upm-package
https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask
설치 후, 아래와 같은 방식으로 사용할 수 있습니다.
// 기본적인 UniTask 사용
using Cysharp.Threading.Tasks;
using UnityEngine;
public class UniTaskExample : MonoBehaviour
{
async void Start()
{
Debug.Log("Start 작업 시작");
await UniTask.Delay(2000); // 2초 대기
Debug.Log("2초 후 작업 실행");
}
}
- UniTask.Delay()는 Task.Delay()보다 효율적입니다.
- async 메서드에서 await를 사용하여 비동기 작업을 실행합니다.
Task와 UniTask의 차이점
UniTask를 이해하려면 먼저 Task와 어떤 점에서 차이가 있는지 알아야 합니다.
Task | UniTask | |
메모리 관리 | 비동기 작업 시 새로운 메모리 할당 (GC 부담 높음) | 할당 없는 구조로 GC 부담 감소 |
유니티 친화성 | 유니티에 특화된 API 부족 | UniTask.DelayFrame(), UniTask.Yield() 등 지원 |
사용 용이성 | C# 표준 API이므로 유니티 외의 환경에서 유용 | 유니티 전용으로 설계 |
성능 | 고성능 환경에서 적합하나, 유니티 환경에서는 오버헤드 | 유니티 환경에서 경량화된 성능 제공 |
// Task 예제
using System.Threading.Tasks;
async void TaskExample()
{
await Task.Delay(2000); // 2초 대기
Debug.Log("Task 완료");
}
// UniTask 예제
using Cysharp.Threading.Tasks;
async void UniTaskExample()
{
await UniTask.Delay(2000); // 2초 대기
Debug.Log("UniTask 완료");
}
- Task.Delay()는 GC에 부담을 줄수있고 유니티 환경에 최적화되지 않습니다.
- 반면 UniTask.Delay()는 유니티에서 성능을 최적화한 API로 더 적합합니다.
UniTask의 기능
프레임 딜레이 및 업데이트 루프 관리
유니티의 Update()와 비동기 작업을 잘 사용하려면 UniTask.Yield()와 UniTask.NextFrame()을 활용합니다.
예제: 특정 프레임마다 작업 실행 - UniTask.NextFrame()
async UniTaskVoid PerformEveryFrame()
{
while (true)
{
Debug.Log("현재 프레임: " + Time.frameCount);
await UniTask.NextFrame();
}
}
이 방법은 애니메이션이나 상태 업데이트를 프레임 단위로 처리할 때 유용합니다.
예제: 특정 조건에서 작업을 지연시키기 - UniTask.Yield()
async UniTaskVoid PerformWithYield()
{
int count = 0;
// 특정 조건에 따라 작업을 지연시키면서 반복
while (count < 5)
{
Debug.Log("작업 실행: " + count);
count++;
// 현재 프레임에서 작업을 잠시 멈추고, 다음 프레임에서 이어서 실행
await UniTask.Yield();
}
Debug.Log("작업 완료");
}
- UniTask.Yield()는 현재 비동기 작업을 다음 프레임에서 이어서 실행하도록 합니다.
- 이 방식은 특정 조건에 맞는 작업을 프레임마다 나누어 처리하고 싶을 때 유용합니다.
- 예시에서는 count 값이 5가 될 때까지 UniTask.Yield()를 사용하여 작업을 매 프레임마다 실행하도록 했습니다.
UniTask.Yield()와 UniTask.NextFrame()의 차이
- UniTask.Yield()는 프레임 단위로 작업을 일시 중단하고, NextFrame()은 현재 프레임 후의 첫 번째 프레임에 작업을 실행합니다.
- UniTask.Yield()는 좀 더 유연하게 사용될 수 있으며, UniTask.NextFrame()은 한 프레임 딜레이를 확실히 사용할 때 사용됩니다.
씬 전환 및 로드 관리
씬 전환 시 UnityEngine.SceneManagement.SceneManager를 ToUniTask()로 변환하여 사용할 수 있습니다.
예제: 씬 로딩
using Cysharp.Threading.Tasks;
using UnityEngine.SceneManagement;
async UniTask LoadNewScene(string sceneName)
{
Debug.Log("씬 로딩 시작");
await SceneManager.LoadSceneAsync(sceneName).ToUniTask();
Debug.Log("씬 로딩 완료");
}
이 방법은 로딩 화면이나 프로그레스 바를 추가할 때 사용할 수 있습니다.
병렬 및 연속 작업 처리
예제: 병렬 작업
여러 비동기 작업을 동시에 실행하고 모든 작업이 완료될 때까지 기다립니다.
async UniTask PerformParallelTasks()
{
var task1 = UniTask.Delay(1000);
var task2 = UniTask.Delay(2000);
var task3 = UniTask.Delay(3000);
await UniTask.WhenAll(task1, task2, task3);
Debug.Log("모든 작업 완료");
}
예제: 연속 작업
async UniTask PerformSequentialTasks()
{
await UniTask.Delay(1000);
Debug.Log("첫 번째 작업 완료");
await UniTask.Delay(2000);
Debug.Log("두 번째 작업 완료");
await UniTask.Delay(3000);
Debug.Log("세 번째 작업 완료");
}
UniTask 활용
NPC 애니메이션 관리
NPC가 대화, 이동, 상호작용을 순서대로 수행하도록 만듭니다.
async UniTask ControlNPC(NPC npc)
{
await npc.PlayAnimation("Talk");
await UniTask.Delay(2000);
await npc.MoveTo(new Vector3(10, 0, 5));
await UniTask.Delay(1000);
await npc.PlayAnimation("Idle");
}
아이템 생성 및 처리
아이템이 생성된 후 일정 시간 뒤에 사라지도록 구현합니다.
async UniTask SpawnItem(GameObject itemPrefab, Vector3 position)
{
var item = GameObject.Instantiate(itemPrefab, position, Quaternion.identity);
Debug.Log("아이템 생성");
await UniTask.Delay(5000); // 5초 후
GameObject.Destroy(item);
Debug.Log("아이템 소멸");
}
멀티플레이어 네트워크 대기
서버에서 응답을 받을 때까지 대기하도록 구현합니다.
async UniTask WaitForServerResponse(Server server)
{
while (!server.HasReceivedResponse)
{
await UniTask.Delay(100);
}
Debug.Log("서버 응답 받음");
}
UniTask 사용 시 유의점
- GC 부담 최소화: UniTask는 효율적이지만, 비동기 작업을 과도하게 사용하면 여전히 성능 문제가 발생할 수 있습니다.
- 코드 가독성: 비동기 작업이 많아지면 코드가 복잡해질 수 있으므로 주의해야합니다.
마무리
UniTask는 유니티 환경에 최적화된 비동기 프로그래밍 라이브러리로, 기존의 Task보다 더 효율적으로 작동합니다. 특히 유니티 게임 개발에서 자주 사용하는 작업을 간단하고 빠르게 처리할 수 있어 생산성을 크게 높여줍니다. 비동기 프로그래밍을 이해하고 UniTask를 적극 활용하면 더 최적화된 게임을 개발할 수 있을 것입니다.
'Unity > 정보' 카테고리의 다른 글
[Unity] 유니티에서 Task 사용하기 (1) | 2024.12.21 |
---|---|
[Unity] 로컬 알림 기능 (Android) (0) | 2024.11.10 |
[Unity] Resources.UnloadUnusedAssets() : 메모리 관리 (0) | 2024.09.28 |
[Unity] 비등방성 필터링(Anisotropic filtering)과 Mipmap (0) | 2024.09.22 |
[Unity] 안티앨리어싱(Anti-Aliasing) (0) | 2024.09.21 |