코드가 작성된 순서대로 순차적으로 실행된다.
간단한 작업에 적합하다.
시간이 오래걸리는 작업에는 부적합.
void LoadData()
{
// 파일에서 데이터를 읽는 시간이 오래 걸리는 작업
string data = ReadFile("data.txt");
ProcessData(data);
}
주 실행 흐름을 차단하지 않고 작업을 처리
async void LoadDataAsync()
{
// 데이터를 비동기적으로 읽어오는 작업
string data = await ReadFileAsync("data.txt");
ProcessData(data);
}
Async : 메서드가 비동기적으로 작동할 수 있음을 나타낸다.
Await : 비동기 작업이 완료될 때까지 현재 메서드의 실행을 일시 중단하고, 완료되면 실행을 계속한다.
using System.Threading.Tasks;
using UnityEngine;
public class AsyncExample : MonoBehaviour
{
async void Start()
{
Debug.Log("데이터 로딩 시작");
await LoadDataAsync();
Debug.Log("데이터 로딩 완료");
}
async Task LoadDataAsync()
{
// 예를 들어, 여기서 외부 API로부터 데이터를 비동기적으로 로딩할 수 있습니다.
await Task.Delay(2000); // 2초간 대기를 시뮬레이션
// 데이터 처리 로직
}
}
고급 사용법? 비동기 작업을 병렬로 실행하여 여러 작업을 동시에 처리하기
public class AdvancedAsyncExample : MonoBehaviour
{
async void Start()
{
Task task1 = PerformTaskAsync("Task 1", 3000);
Task task2 = PerformTaskAsync("Task 2", 2000);
await Task.WhenAll(task1, task2);
Debug.Log("모든 작업 완료");
}
async Task PerformTaskAsync(string taskName, int delay)
{
Debug.Log($"{taskName} 시작");
await Task.Delay(delay);
Debug.Log($"{taskName} 완료");
}
}
고급 사용법? 비동기 작업 중 발생하는 예외를 예쁘게 처리하기
async Task PerformTaskWithExceptionHandlingAsync()
{
try
{
// 여기서 예외가 발생할 수 있는 비동기 작업을 수행합니다.
await Task.Delay(1000);
throw new System.Exception("에러 발생");
}
catch (System.Exception e)
{
Debug.LogError($"비동기 작업 중 에러 발생: {e.Message}");
}
}
이미지 처리, 데이터 로딩, 네트워크 통신
예) 대규모 게임맵을 로딩할 때, 비동기적으로 세그먼트를 로드하여 사용자가 기다리는 시간을 최소화 한다.
public async void LoadMapSegmentsAsync()
{
List<Task> loadingTasks = new List<Task>();
for (int i = 0; i < numberOfSegments; i++)
{
loadingTasks.Add(LoadSegmentAsync(i));
}
await Task.WhenAll(loadingTasks);
Debug.Log("모든 세그먼트 로드 완료.");
}
async Task LoadSegmentAsync(int segmentIndex)
{
// 게임 맵의 각 세그먼트를 비동기적으로 로딩하는 로직
await Task.Delay(1000); // 로딩 시간 시뮬레이션
Debug.Log($"Segment {segmentIndex} loaded.");
}
제한된 자원 내에서 고려할 것
메모리 누수나 성능 저하에 영향을 미친다.
비동기 작업은 늘 모니터링을 해야한다.
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
async Task LoadDataAsync(CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
{
Debug.Log("비동기 작업 취소됨");
return;
}
// 데이터 로딩 로직
await Task.Delay(2000, cancellationToken);
}
// 작업 취소 시
void CancelLoading()
{
cancellationTokenSource.Cancel();
}
일반 함수와 달리 여러 프레임에 걸쳐서 실행될 수 있고, 일시 중단하고 다시 시작할 수도 있다.
시간 지연, 비동기적 작업 처리, 순차적 이벤트 처리
public class FadeScript : MonoBehaviour
{
void Start()
{
// 코루틴 시작
StartCoroutine(FadeOut());
}
IEnumerator FadeOut()
{
float fadeDuration = 3f;
float elapsedTime = 0f;
while (elapsedTime < fadeDuration)
{
elapsedTime += Time.deltaTime;
float alpha = 1 - (elapsedTime / fadeDuration);
// 여기서는 예를 들어 게임 오브젝트의 투명도를 조절하는 로직이 들어갈 것임.
yield return null; // 다음 프레임까지 기다립니다.
}
}
}
IEnumerator ExampleCoroutine()
{
Debug.Log("코루틴 시작");
yield return new WaitForSeconds(2);
Debug.Log("2초 후");
}
IEnumerator GameLoopCoroutine()
{
while (true) // 무한 루프를 사용하여 게임 루프를 시뮬레이션
{
yield return StartCoroutine(PerformTask());
// 다른 게임 루프 태스크들
}
}
IEnumerator PerformTask()
{
// 특정 태스크 수행
yield return new WaitForSeconds(1); // 1초 대기
// 태스크 완료 후 로직
}
void Start()
{
StartCoroutine(CoroutineA());
StartCoroutine(CoroutineB());
}
IEnumerator CoroutineA()
{
// Coroutine A의 로직
yield return new WaitForSeconds(2);
// Coroutine A 완료 후 로직
}
IEnumerator CoroutineB()
{
// Coroutine B의 로직
yield return new WaitForSeconds(3);
// Coroutine B 완료 후 로직
}
IEnumerator SequentialCoroutines()
{
yield return StartCoroutine(Task1());
yield return StartCoroutine(Task2());
// 다음 태스크
}
IEnumerator Task1()
{
// Task 1의 로직
yield return new WaitForSeconds(2); // 대기
}
IEnumerator Task2()
{
// Task 2의 로직
yield return new WaitForSeconds(3); // 대기
}
IEnumerator LoadGameData()
{
var loadDataTask = LoadDataAsync(); // 비동기 데이터 로딩 시작
yield return new WaitUntil(() => loadDataTask.IsCompleted); // 로딩 완료 대기
if (loadDataTask.IsFaulted)
{
// 에러 처리
}
else
{
// 데이터 처리
}
}
async Task LoadDataAsync()
{
// 데이터 비동기 로딩 로직
await Task.Delay(1000); // 비동기 로딩 시뮬레이션
}