2025. 4. 21. 21:16ใ[Unity] Game Programing
๐ TIL - Unity ๋น๋๊ธฐ ์์ ์ต์ ํ๋ฅผ ์ํ UniTask ํ์ต
๋ ์ง: 2025๋ 4์ 21์ผ
๐งญ UniTask๋ ๋ฌด์์ธ๊ฐ?
UniTask๋ Cysharp์์ ๊ฐ๋ฐํ Unity ์ ์ฉ ๊ฒฝ๋ ๋น๋๊ธฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค. ๊ธฐ๋ณธ .NET์ Task ๊ตฌ์กฐ๋ณด๋ค ๋ ๊ฐ๋ณ๊ณ , Garbage-Free์ ๊ฐ๊น์ด ํ๊ฒฝ์ ์ ๊ณตํ์ฌ Unity์์์ ์ฑ๋ฅ ์ ํ๋ฅผ ์ค์ธ๋ค.
Unity๋ ๊ธฐ๋ณธ์ ์ผ๋ก async/await๋ฅผ ์ฌ์ฉํ ์ ์์ผ๋, System.Threading.Tasks.Task ๊ธฐ๋ฐ์ ๊ตฌ์กฐ๋ GC ๋น์ฉ์ด ํฌ๊ณ , Unity์ ํ๋ ์ ์ฌ์ดํด๊ณผ ์๋ฒฝํ ์ด์ธ๋ฆฌ์ง ์๊ธฐ ๋๋ฌธ์ UniTask๊ฐ ๋์
๋์๋ค.
๐ง ์ฃผ์ ํน์ง
- Unity 2019.4 ์ด์์์ ์ฌ์ฉ ๊ฐ๋ฅ
- Task๋ณด๋ค ํจ์ฌ ์ ์ GC ๋น์ฉ
- Unity์
YieldInstruction(WaitForSeconds,WaitUntil๋ฑ)์ ์๋ฒฝํ ๋์ฒด - ํ์์ค์ผ์ผ ๋ฌด์ ์ฌ๋ถ ๋ฑ ์ ์ฐํ ์ค์ ๊ฐ๋ฅ
- Unity ๋ฉ์ธ ์ค๋ ๋์์ ์์ ํ ์ ํ ์ ๊ณต
๐ UniTask vs Task ์ฐจ์ด์
| ํญ๋ชฉ | System.Threading.Tasks.Task | UniTask |
|---|---|---|
| GC ๋น์ฉ | ๋์ (๋ฐ์ฑ, ์ํ ๊ฐ์ฒด) | ๋ฎ์ (๊ตฌ์กฐ์ฒด ๊ธฐ๋ฐ, ๊ฑฐ์ 0) |
| ์ฑ๋ฅ | ๋น๋๊ธฐ ํจ์๊ฐ ๋ง์์ง๋ฉด ์ฑ๋ฅ ์ ํ | ์์ฒ ๊ฐ๋ ๋ฌธ์ ์์ด ์ฒ๋ฆฌ ๊ฐ๋ฅ |
| Unity ํตํฉ | ์ง์ ์ ๋จ | await WaitForSeconds ๊ฐ๋ฅ |
| ํ์์ค์ผ์ผ ๋ฌด์ | ๋ถ๊ฐ๋ฅ | ๊ฐ๋ฅ (IgnoreTimeScale) |
| API ํตํฉ | ํ์ค Task ๊ธฐ๋ฐ | Unity ์นํ์ ์ธ API ์ ๊ณต |
๐ ๊ธฐ๋ณธ ์ฌ์ฉ ์์
using Cysharp.Threading.Tasks;
using UnityEngine;
public class UniTaskExample : MonoBehaviour
{
private async void Start()
{
Debug.Log("3์ด ๋๊ธฐ ์์...");
await UniTask.Delay(3000);
Debug.Log("3์ด ํ ์คํ๋จ");
await DoSomethingAsync();
Debug.Log("๋ชจ๋ ์์
์๋ฃ");
}
private async UniTask DoSomethingAsync()
{
await UniTask.Yield();
Debug.Log("ํ๋ ์ ์ดํ ์คํ");
}
}
โฑ๏ธ ์๊ฐ ๋๊ธฐ API
UniTask๋ ๋ค์ํ ์๊ฐ ๊ธฐ๋ฐ ๋น๋๊ธฐ API๋ฅผ ์ ๊ณตํ๋ค.
UniTask.Delay(int milliseconds)UniTask.DelayFrame(int frameCount)UniTask.WaitUntil(() => ์กฐ๊ฑด)UniTask.WaitWhile(() => ์กฐ๊ฑด)
await UniTask.WaitUntil(() => player.IsDead);
๐๏ธ UniTask์ ๋ด๋ถ ๊ตฌ์กฐ
UniTask๋ ๊ตฌ์กฐ์ฒด(struct) ๊ธฐ๋ฐ์ผ๋ก GC๋ฅผ ์ ๋ฐํ์ง ์๋๋ค. ๋ด๋ถ์ ์ผ๋ก๋ ์ํ ๋จธ์ ์ ํฌํจํ์ง๋ง, ๋ฐ์ฑ(boxing)์ด ์๋ ๋ฐฉ์์ผ๋ก ์ต์ ํ๋๋ค. ๋ํ awaiter๋ฅผ ์ปค์คํฐ๋ง์ด์ง ํ ์ ์์ด ๋ค์ํ Unity ์ ์ฉ ๋น๋๊ธฐ ์ํฉ์ ๋์ ๊ฐ๋ฅํ๋ค.
๋จ์ํ Task์ ๊ตฌ์กฐ๋ฅผ ์๋ฎฌ๋ ์ดํธํ๋ ๊ฒ์ด ์๋๋ผ, C# async/await ํค์๋๋ฅผ ์ต๋ํ ํ์ฉํ ์ ์๋๋ก ์ค๊ณ๋์๋ค.
๐ CancellationToken ์ง์
Unity๋ ์ฌ ์ ํ์ด๋ ์ค๋ธ์ ํธ ํ๊ดด ์ ์์ ํ ๋น๋๊ธฐ ์์
์ทจ์๊ฐ ์ค์ํ๋ค. UniTask๋ CancellationToken์ ์๋ฒฝํ ์ง์ํ๋ฉฐ, this.GetCancellationTokenOnDestroy()์ฒ๋ผ MonoBehaviour์ ๊ฒฐํฉ ๊ฐ๋ฅํ๋ค.
private async UniTaskVoid LoadDataAsync(CancellationToken token)
{
try
{
await UniTask.Delay(5000, cancellationToken: token);
Debug.Log("์๋ฃ๋จ");
}
catch (OperationCanceledException)
{
Debug.Log("์์
์ด ์ทจ์๋์์ต๋๋ค.");
}
}
๐ฆ UniTaskVoid์ UniTask
- UniTask: ๋ฐํ๊ฐ์ด ์๋ ์ผ๋ฐ ๋น๋๊ธฐ ํจ์
- UniTaskVoid: fire-and-forget ์ฉ๋. ์์ธ ํธ๋ค๋ง์ด ์ด๋ ต๊ธฐ ๋๋ฌธ์ ์ฃผ์๊ฐ ํ์
๊ฒ์ ๋ก์ง์๋ UniTask๋ฅผ ์ต๋ํ ์ฌ์ฉํ๊ณ , UniTaskVoid๋ ์ด๋ฒคํธ ์ฝ๋ฐฑ ์ฒ๋ฆฌ๋ MonoBehaviour์ Start ๋ฑ์์๋ง ์ ํ์ ์ผ๋ก ์ฌ์ฉํ๋ค.
๐งช ํ ์คํธ ๋ฐ ๋๋ฒ๊น ํ
- ๋น๋๊ธฐ ๋ก์ง ์ค๋จ ์ Debug.Log๋ก ์์น๋ฅผ ์ถ์
- Try-Catch ๋ธ๋ก์ ์ ๊ทน ํ์ฉํ์ฌ ์์ธ ํ์ธ
UniTask.SwitchToMainThread()์ฌ์ฉ ์์ ํ์ธ
๐ GC ๋ฐ ์ฑ๋ฅ ์ต์ ํ
- Update ์์์
async void์ฌ์ฉ ๊ธ์ง - ๊ฐ๋ฅํ ๋ฐ๋ณต ๋น๋๊ธฐ ๋ก์ง์
UniTask.Yield๋๋DelayFrameํ์ฉ - ๋ฐ๋ณต์ ์ผ๋ก ํธ์ถ๋๋ ๋ฉ์๋๋ UniTask.Lazy ๋๋ UniTask.Defer ๋ฑ์ ํตํด ์์ฑ ์ต์ํ
๐ ์ฐธ๊ณ ๋งํฌ
'[Unity] Game Programing' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| TIL : ์ ๋ํฐ ๊ฒ์ ์์คํ ๊ตฌํ (1) | 2025.04.29 |
|---|---|
| TIL: AlivePlayer ์์คํ ์ฌ์ธต ๋ถ์ (์ํ ๋จธ์ , ๋ฐ์ดํฐ ๊ด๋ฆฌ, ์ปดํฌ๋ํธ ๊ตฌ์กฐ) (1) | 2025.04.28 |
| ์บ๋ฆญํฐ ๊ฐ๋ฐ TIL (Today I Learned) (0) | 2025.04.25 |
| Today I Learned - Unity์์ Google Sheets ์ฌ์ฉ๋ฒ ์ ๋ฆฌ (0) | 2025.04.24 |
| UniRx: ์ ๋ํฐ์์์ ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ (1) | 2025.04.08 |