ColorPuzzle 프로젝트에 UniTask 적용

이준영·2026년 1월 20일

이전에 Addressables쪽 코드를 그냥 Task를 이용해서 비동기 코드를 구현했는데, 이 부분을 UniTask로 고쳐보기로 했다.

현재 프로젝트에 적용하기

이전 코드

using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.ResourceManagement.AsyncOperations;

public enum UIPrefabs
{
    Alert,
    Confirm,
    StageButton,
    StageContainer,
}

/// <summary>
/// UI 프리팹을 로드하고, 인스턴스화된 객체와 Addressables 핸들을 매핑하여 관리합니다.
/// </summary>
public class UIPrefabManager : MonoBehaviour
{
    public static UIPrefabManager Instance { get; private set; }
    
    private Dictionary<GameObject, AsyncOperationHandle<GameObject>> activePrefabHandles = 
        new Dictionary<GameObject, AsyncOperationHandle<GameObject>>();

    private void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }


    public async Task<GameObject> ShowUI(UIPrefabs address)
    {
        AsyncOperationHandle<GameObject> loadHandle = ResourceLoader.LoadAssetAsync<GameObject>(address.ToString());
        
        await loadHandle.Task;

        if (loadHandle.Status == AsyncOperationStatus.Succeeded)
        {
            GameObject prefabAsset = loadHandle.Result;
            Transform uiParent = FindObjectOfType<Canvas>().transform;
            GameObject instance = ObjectPool.Get(prefabAsset, uiParent);
            
            activePrefabHandles.Add(instance, loadHandle);
            
            return instance;
        }
        else
        {
            ResourceLoader.Release(loadHandle);
            
            return null;
        }
    }
    
    public void CloseUI(GameObject instance)
    {
        if (activePrefabHandles.TryGetValue(instance, out AsyncOperationHandle<GameObject> handle))
        {
            ObjectPool.Release(instance);
            
            ResourceLoader.Release(handle); 
            
            activePrefabHandles.Remove(instance);
        }
        else
        {
            Destroy(instance); 
        }
    }
}

해당 코드에서 단점들이 좀 보였는데,

  1. FindObjectOfType로 사용해서 Canvas를 찾고 있는데, 만약 잦은 호출이 발생한다면 성능 저하가 있는 메서드 이다.

  2. await 이후에 loadHandle.Status를 확인해서 에러를 처리하고 있는데, try-catch문을 이용하는 방식이 더 깔끔하다.

코드 개선하기

Canvas 찾는 방식 변경

UIPrefabManager
UICanvasMarker
  • 현재 메인 캔버스를 등록하는 메서드를 만들어서 각 씬에 캔버스에서 메서드를 호출하는 방식으로 캔버스 문제를 해결했다.

try-catch문으로 변경

이전 ShowUI
개선한 ShowUI
  • 이전 ShowUI에서는 냅다 호출과 대기를 하고 성공 여부를 판단함.
  • 개선된 ShowUI에서는 호출에서 오류가 발생하면 바로 catch문에서 오류를 판별한다.

테스트

테스트
  • Adressables로 불러오는 파일의 크기가 크지 않아서 그런지, UniTask Tracker에 찍히진 않았다.
profile
게임 개발자가 되기 위해서 공부하는 중입니다.

0개의 댓글