유니티 코루틴의 단점
- 서버로부터 받은 값을 IEnumrator Function()에서 리턴할 수 없음
(특정 값을 return 키워드를 사용해 바로 반환할 수 없다는 의미)
- StartCoroutin 을 사용할 때마마 GC할당이 높음.
특히 yield return new 를 사용할때마다 New 로 인한 할당이 지속적으로 발생
// GC(가비지 컬렉션) : 사용하지 않는 메모리를 정리하는 작업
// GC가 실행되면 프로그램이 잠시 멈추는 일이 발생할 수 있음.
// GC가 자주 동작하면 성능 저하와 프레임 드랍이 발생할 가능성이 높아짐.
즉, GC할당이 높아지면, 프레임 드랍이 많이 발생하고, 메모리 낭비가 심해짐.
UniTask 의 장점
- 서버로부터 받은 값을 Return 할 수 있다.
- Struct 기반으로 제작되어 있어, Zero Allocation이 특징
// Zero Allocation : 실행 중에 추가적인 메모리를 할당하지 않는다는 의미
// 즉, 프로그램이 UniTask를 사용할 때 새로운 메모리 객체를 생성하거나
가비지 컬렉션(GC)을 유발하지 않도록 설계되었다는 것을 뜻
- UniTask.Yield, UniTask.Dealy, UniTask.DelayFrame 처럼
Coroutine과 유사한 기능을 제공
- 메모리 누수를 방지하기 위한 TaskTracker 창 지원.
// TaskTracke : UniTask로 생성된 비동기 작업들을 추적하고 관리하는 도구
// 비동기 작업 : 시간이 오래 걸리는 작업을 다른 작업과 동시에 실행하도록 처리하는
프로그래밍 방식.
즉, 다른 코드의 실행을 막지 않고 병렬적으로 실행되는 작업
// 메모리 누수 방지와 디버깅 편의성을 제공하는 역할을 수행
// 메모리 누수: 프로그램이 더 이상 사용하지 않는 메모리를 해제하지 않고 계속 점유하는 상황
// 시스템의 사용 가능한 메모리가 줄어들고, 결국 프로그램이나 시스템 성능이 저하되거나 충돌이 발생할 수 있음.
1. 기존 코루틴 방식과 UniTask 방식으로 비동기 작업(시간 지연) 을 처리할 때
public class TestCode : MonoBehaviour
{
// 1. 기존 코루틴 방식으로 비동기 작업(시간 지연) 을 처리할때
private IEnumerator WaitSecond()
{
yield return new WaitForSeconds(1f);
Debug.Log("1초가 지났다");
}
// 1. UniTask 방식으로 비동기 작업(시간 지연) 을 처리할때
// 유니티의 코루틴보다 더 성능이 좋고 코드가 간결함
private async UniTaskVoid WaitSecondAsync()
{
// await: 현재 작업을 비동기로 처리하고, 대기한 후에 다음 줄을 실행
// UniTask.Delay : 주어진 시간 동안 비동기적으로 대기
await UniTask.Delay(TimeSpan.FromSeconds(1f));
Debug.Log("1초가 지났다");
}
private void Start()
{
// 1. 기존 코루틴 방식
StartCoroutine(WaitSecond());
// 1. UniTask 방식
WaitSecondAsync().Forget();
}
}
2. 기존 코루틴 방식과 UniTask 방식으로 타임 스케일을 무시하는 작업을 처리할 때
타임 스케일

public class TestCode : MonoBehaviour
{
// 2. 기존 코루틴 방식으로 타임 스케일을 무시하는 작업을 처리할 때(타임
private IEnumerator WaitSecond()
{
// 타임 스케일이 0 이되어도 동작하는 코드
yield return new WaitForSecondsRealtime(1f);
Debug.Log("1초가 지났다");
}
// 2. UniTask 방식으로 타임 스케일을 무시하는 작업을 처리할 때
// 유니티의 코루틴보다 더 성능이 좋고 코드가 간결함
private async UniTaskVoid WaitSecondAsync()
{
// await: 현재 작업을 비동기로 처리하고, 대기한 후에 다음 줄을 실행
// UniTask.Delay : 주어진 시간 동안 비동기적으로 대기
// 타임 스케일이 0 이되어도 동작하는 코드
await UniTask.Delay(TimeSpan.FromSeconds(1f), DelayType.UnscaledDeltaTime);
Debug.Log("1초가 지났다");
}
private void Start()
{
// 타임 스케일을 0으로 설정
Time.timeScale = 0;
// 2. 기존 코루틴 방식
StartCoroutine(WaitSecond());
// 2. UniTask 방식
WaitSecondAsync().Forget();
}
}
3. 기존 코루틴 방식과 UniTask 방식으로 어떤 기능이 특정 조건이 되었을때 실행하도록 하고 싶을 때
public class TestCode : MonoBehaviour
{
// _count 맴버변수 생성
public int _count;
// 3. 기존 코루틴 방식으로 어떤 기능이 특정 조건이 되었을때 실행하도록 하는 코드
private IEnumerator Wait3Count()
{
// _count 맴버변수가 3이 되어야 하기의 Debug.Log가 실행됨
yield return new WaitUntil(() => _count == 3);
Debug.Log("카운트가 3이 되었다.");
}
// 3. UniTask 방식으로 어떤 기능이 특정 조건이 되었을때 실행하도록 하는 코드
// 유니티의 코루틴보다 더 성능이 좋고 코드가 간결함
private async UniTaskVoid Wait3CountAsync()
{
// _count 맴버변수가 3이 되어야 하기의 Debug.Log가 실행됨
await UniTask.WaitUntil(() => _count == 3);
Debug.Log("카운트가 3이 되었다.");
}
private void Start()
{
// 3. 기존 코루틴 방식
StartCoroutine(Wait3Count());
// 3. UniTask 방식
Wait3CountAsync().Forget();
}
}
4. 기존 코루틴 방식과 UniTask 방식으로 웹에 있는 이미지URL주소를 가져와서
텍스쳐 파일 또는 스프라이트로 바꾸는 작업을 하고 싶을 때
- 코루틴 방식
public class TestCode : MonoBehaviour
{
// 웹에서 가져온 사과 이미지 URL주소를 맴버변수로 설정
private const string AppleImage = "https://cdn.mkhealth.co.kr/news/photo/202010/50970_51164_4758.jpg";
// UI 요소중에 RawImage 를 통해서, 불러온 텍스쳐를 UI단에다 올림
public RawImage appleimage1;
// 4. 기존 코루틴 방식으로 웹에 있는 이미지URL주소를 가져와서 텍스쳐 파일 또는 스프라이트로 바꾸는 작업을 하고 싶을 때
private IEnumerator WaitGetWebTexture(UnityAction<Texture2D> action)
{
// 웹에서 텍스쳐를 받아오기
UnityWebRequest request = UnityWebRequestTexture.GetTexture(AppleImage);
yield return request.SendWebRequest();
// 이미지를 가져오는데 실패하는 코드를 작성
// or는 Result 타입에 사용되는 메서드로, 하나의 값이 None 또는 Err일 경우 다른 값을 반환하는 방식으로 동작
if (request.result is UnityWebRequest.Result.ConnectionError or UnityWebRequest.Result.ProtocolError)
{
// 에러의 처리
Debug.LogError(request.error);
}
// 이미지를 가져오는데 성공 코드를 작성
else
{
// 성공 처리
Texture2D texture = ((DownloadHandlerTexture)request.downloadHandler).texture;
// 받아언 텍스쳐를 리턴처리
action.Invoke(texture);
}
}
private void Start()
{
// 4. 기존 코루틴 방식
StartCoroutine(WaitGetWebTexture(texture =>
{
// 매개변수인 appleimage1 를 사용함
appleimage1.texture = texture;
}));
}
}
- UniTask 방식
public class TestCode : MonoBehaviour
{
// 웹에서 가져온 사과 이미지 URL주소를 맴버변수로 설정
private const string AppleImage = "https://cdn.mkhealth.co.kr/news/photo/202010/50970_51164_4758.jpg";
// UI 요소중에 RawImage 를 통해서, 불러온 텍스쳐를 UI단에다 올림
public RawImage appleimage1;
// 4. UniTask 방식으로 웹에 있는 이미지URL주소를 가져와서 텍스쳐 파일 또는 스프라이트로 바꾸는 작업을 하고 싶을 때
private async UniTask<Texture2D> WaitGetWebTextureAsync()
{
// 웹에서 텍스쳐를 받아오기
UnityWebRequest request = UnityWebRequestTexture.GetTexture(AppleImage);
await request.SendWebRequest();
// or 는 Result 타입에 사용되는 메서드로, 하나의 값이 None 또는 Err 일 경우 다른 값을 반환하는 방식으로 동작
if (request.result is UnityWebRequest.Result.ConnectionError or UnityWebRequest.Result.ProtocolError)
{
// 실패 처리
Debug.LogError(request.error);
}
// 이미지를 가져오는데 성공 코드를 작성
else
{
// 성공처리
Texture2D texture = ((DownloadHandlerTexture)request.downloadHandler).texture;
// 텍스쳐를 리턴처리
return texture;
}
return null;
}
private async UniTaskVoid GetImageAsync()
{
// 4. UniTask 방식
Texture2D texture = await WaitGetWebTextureAsync();
// 매개변수인 appleimage1.을 사용함
appleimage1.texture = texture;
}
private void Start()
{
// 4. UniTask 방식으로 실행
GetImageAsync().Forget();
}
}
5. 기존 코루틴 방식과 UniTask 방식으로 중간에 종료, 또는 일시정지 하는 기능을 구현하고 싶을 때
- 코루틴 방식
public class TestCode : MonoBehaviour
{
// 5. 코루틴 자료형 생성
private Coroutine _coroutine;
// 5. 기존 코루틴 방식으로 중간에 종료, 또는 일시정지 하는 기능을 구현하고 싶을 때
private IEnumerator Wait3Seconds()
{
yield return new WaitForSeconds(3f);
Debug.Log("3초가 지났습니다.");
}
private void Start()
{
// 5. 기존 코루틴 방식
_coroutine = StartCoroutine(Wait3Seconds());
}
private void Update()
{
// 5. 스페이스바를 누르면 StopCoroutine(); 실행
if (Input.GetKeyDown(KeyCode.Space))
{
StopCoroutine(_coroutine);
}
}
}
- UniTask 방식
// CancellationTokenSource : Cancel 타이밍을 원할 때 처리 가능(직접적인 Dispose호출 필요)
// this.GetCancellationTokenOnDestroy : Destroy될때 Cancel 및 Dispose 를 수행함
public class TestCode : MonoBehaviour
{
// CancellationTokenSource 맴버변수를 생성
private CancellationTokenSource _source = new();
// 5. UniTask 방식으로 중간에 종료, 또는 일시정지 하는 기능을 구현하고 싶을 때
private async UniTaskVoid Wait3Second()
{
await UniTask.Delay(TimeSpan.FromSeconds(3), cancellationToken: _source.Token);
Debug.Log("3초가 지났다.");
}
// Wait3Second() 함수를 실행
private void Start()
{
Wait3Second().Forget();
}
// 스페이스바를 눌렀을때 중지
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
_source.Cancel();
}
}
}
++ 추가적으로 오브젝트가 삭제되거나 비활성일때 취소시키고 싶으면 ++
public class TestCode : MonoBehaviour
{
// CancellationTokenSource 맴버변수를 생성
private CancellationTokenSource _source = new();
// 5. UniTask 방식으로 중간에 종료, 또는 일시정지 하는 기능을 구현하고 싶을 때
private async UniTaskVoid Wait3Second()
{
await UniTask.Delay(TimeSpan.FromSeconds(3), cancellationToken: _source.Token);
Debug.Log("3초가 지났다.");
}
// Wait3Second() 함수를 실행
private void Start()
{
Wait3Second().Forget();
}
// 스페이스바를 눌렀을때 중지
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
_source.Cancel();
}
}
// 오브젝트가 삭제되면 진행중인 Task를 취소하고, Dispose(리소스나 객체를 정리 및 헤제) 하도록 처리
private void OnDestroy()
{
_source.Cancel();
_source.Dispose();
}
// _source 가 null 이 아니면, Dispose(리소스나 객체를 정리 및 헤제) 하도록 처리
private void OnEnable()
{
if(_source != null)
_source.Dispose();
// 그 다음에 새로운 new 를 처리해서 CancellationTokenSource 를 대입하게 만듬
_source = new CancellationTokenSource();
}
// 오브젝트가 비활성화 되면 Task를 취소하도록 처리
private void OnDisable()
{
_source.Cancel();
}
}
++ 게임 오브젝트가 씬에서 제거될때 자동으로 task를 중단만(비활성화는 포함 x)시키려면 ++
public class TestCode : MonoBehaviour
{
// 5. UniTask 방식으로 중간에 종료, 또는 일시정지 하는 기능을 구현하고 싶을 때
private async UniTaskVoid Wait3Second()
{
// this.GetCancellationTokenOnDestroy() : 게임 오브젝트가 씬에서 제거되면 자동으로 task를 중단
await UniTask.Delay(TimeSpan.FromSeconds(3), cancellationToken: this.GetCancellationTokenOnDestroy());
Debug.Log("3초가 지났다.");
}
// Wait3Second() 함수를 실행
private void Start()
{
Wait3Second().Forget();
}
}
** 6. UniTask 방식으로 실행중인 Task 추적하기 (기존 코루틴 방식에서는 존재 X)
// ** 6. UniTask 방식으로 실행중인 Task 추적하기 (기존 코루틴 방식에서는 존재 X)
// Window -> UniTask Tracker 를 들어가서 Enable AutoReload, Enable Tracking, Enable StackTrace 들을
// 전부 활성화시키고 게임을 실행. 실행시키면 현재 진행중인 Tracker 를 추적해서, 메모리가 누수가 되고 있는지 아닌지 확인가능.
public class TestCode : MonoBehaviour
{
// 3초후에 해당 코드를 실행
private async UniTaskVoid Wait3Seconds()
{
await UniTask.Delay(TimeSpan.FromSeconds(3));
Debug.Log("3초가 지났다.");
}
private void Start()
{
Wait3Seconds().Forget();
}
}
'게임 개발(유니티) > 멋쟁이 사자처럼 3기_회고록' 카테고리의 다른 글
| 유니티 디자인패턴_Observer 패턴 (0) | 2025.01.09 |
|---|---|
| 유니티 디자인패턴_Command 패턴 (0) | 2025.01.08 |
| [멋쟁이사자처럼 유니티 TIL] 2024_12_30~31 강의 요약 및 정리(5) (0) | 2025.01.05 |
| [멋쟁이사자처럼 유니티 TIL] 2024_12_30~31 강의 요약 및 정리(3) (0) | 2025.01.05 |
| [멋쟁이사자처럼 유니티 TIL] 2024_12_30~31 강의 요약 및 정리(4) (0) | 2025.01.05 |