카테고리 없음

Unity 공용 라이브러리(Common) 개발기 — 2

blacknabis 2026. 2. 12. 00:53

Unity 프로젝트를 여러 개 진행하다 보면 매번 같은 코드를 복붙하게 됩니다.
"이거 한 번 정리하면 두고두고 쓸 텐데…" 라는 생각으로 Common 라이브러리를 만들었습니다.


🎯 목표

  • 프로젝트 간 재사용 가능한 공용 코드 정리
  • GC 최적화, 편의성 극대화
  • 한글 주석으로 팀원도 쉽게 이해 가능
  • 계층화된 UI 시스템으로 팝업/HUD/화면 전환 일관성 확보

📦 구현한 유틸리티 (18개)

1순위 — 거의 모든 프로젝트에서 필수

클래스 한 줄 설명
ObjectPool 프리팹 오브젝트 풀링. Get() / Release() / PreWarm()
EventBus 전역 이벤트 시스템. Subscribe<T>() / Publish<T>()
WaitCache new WaitForSeconds() GC 제거. WaitCache.Get(0.5f)
PlayerPrefsHelper bool, enum, DateTime, JSON 직렬화 지원

EventBus 사용 예:

// 이벤트 정의
public struct PlayerDiedEvent { public int score; }

// 구독
EventBus.Subscribe<PlayerDiedEvent>(e => ShowGameOver(e.score));

// 발행
EventBus.Publish(new PlayerDiedEvent { score = 1500 });

WaitCache 사용 예:

// Before ❌ — 매번 GC 발생
yield return new WaitForSeconds(0.5f);

// After ✅ — 캐시된 인스턴스 재사용
yield return WaitCache.Get(0.5f);

2순위 — 모바일 필수 + 코드 간결화

클래스 한 줄 설명
SafeAreaHelper 노치/펀치홀 대응 자동 레이아웃
CoroutineExtensions this.Delay(1f, callback) 한 줄 딜레이
CollectionExtensions list.GetRandom(), Shuffle() (GC-free)
StringExtensions 숫자 콤마, 시간 포맷, K/M 축약
ColorExtensions color.WithAlpha(0.5f), Hex 변환

CoroutineExtensions 사용 예:

// Before ❌
StartCoroutine(DelayCoroutine());
IEnumerator DelayCoroutine() {
    yield return new WaitForSeconds(1f);
    DoSomething();
}

// After ✅
this.Delay(1f, () => DoSomething());

3순위 — 게임 로직 지원

클래스 한 줄 설명
SimpleStateMachine Enum 기반 FSM. Enter/Update/Exit 콜백
AudioHelper BGM/SFX 싱글톤. 볼륨, 페이드, 자동 저장
ScreenTransition 씬 전환 페이드. FadeOutIn(loadScene)
DebugLogger 카테고리 로깅. 릴리스 빌드 자동 제거

4순위 — 생산성 부스터

클래스 한 줄 설명
Timer 카운트다운/업, 일시정지, 반복, 콜백
VectorExtensions pos.WithY(0), Flat(), RandomInCircle()
MathUtils Chance(30) 확률, Remap(), Damp()
UIButtonExtensions SetOnClick(), 연타 방지 쿨다운
SceneExtensions 비활성 포함 씬 내 컴포넌트 검색

🏗️ UI 프레임워크

기존 BaseUI는 Show/Hide만 있는 껍데기였습니다. 이걸 레이어 기반 UI 관리 시스템으로 완전히 재설계했습니다.

아키텍처

UIHelper (static)  ← 호출 코드에서 사용
   ↓
UIManager (싱글톤)
 ├ 레이어별 Canvas 자동 생성
 │   HUD(0) → Screen(100) → Popup(200) → Overlay(300)
 ├ UI 인스턴스 캐시 (Dictionary<Type, BaseView>)
 ├ 팝업 스택 (List<BasePopup>)
 └ Back Key 라우팅 (팝업 → View 순)
   ↓
기본 클래스
 ├ BaseView   — 전체 화면 (CanvasGroup 페이드 내장)
 ├ BasePopup  — 모달 (딤드 배경, 닫기 가드)
 ├ BaseHUD    — 항상 표시 (HP, 점수)
 └ BaseWidget — 재사용 위젯 (스크롤 아이템)

사용 예

// 화면 전환 — Resources/UI/ 에서 자동 로드
UIHelper.Show<MainMenuView>();

// 팝업 + 닫기 콜백
UIHelper.ShowPopup<SettingsPopup>(onClose: () => SaveSettings());

// HUD 갱신
UIHelper.Get<ScoreHUD>()?.Refresh(currentScore);

// 씬 전환 시 전체 정리
UIHelper.ClearAll();

BasePopup 핵심 기능

public class ConfirmPopup : BasePopup
{
    [SerializeField] private Button confirmButton;

    protected override void OnInit()
    {
        base.OnInit();
        confirmButton.SetOnClick(OnConfirm);
    }

    // 닫기 전 확인 (false 반환 시 닫기 차단)
    protected override bool OnCloseRequested()
    {
        return hasUnsavedChanges == false;
    }
}
  • ✅ 딤드 배경 자동 생성/제거
  • ✅ 딤드 클릭으로 닫기 (옵션)
  • ✅ Back Key 처리
  • ✅ 닫기 가드 (OnCloseRequested)
  • ✅ UIManager 팝업 스택 연동

📁 최종 폴더 구조

Assets/Scripts/Common/
├── App/           AppManagerBase, SceneBase, Appdelegate, ISceneController
├── Patterns/      MonoSingleton, ObjectPool, EventBus, SimpleStateMachine
├── Extensions/    Object, GameObject, Transform, UI, Coroutine,
│                  Collection, String, Color, Vector, UIButton, Scene
├── Utils/         WaitCache, PlayerPrefsHelper, AudioHelper,
│                  DebugLogger, Timer, MathUtils
└── UI/            UIManager, UIHelper, UILayer, BaseView, BasePopup,
                   BaseHUD, BaseWidget, SafeAreaHelper, ScreenTransition

💡 설계 원칙

  1. IsNull() / IsNotNull() — Unity fake null 대응 전용 확장 메서드로 통일
  2. GC 최적화 — WaitCache, ObjectPool, GC-free Collection 확장
  3. Domain Reload 대응 — EventBus, WaitCache에 [RuntimeInitializeOnLoadMethod]
  4. 한글 주석 — 모든 public API에 XML 문서 주석 (한국어)
  5. MonoSingleton — AudioHelper, ScreenTransition, UIManager 등 DontDestroyOnLoad 자동 처리

🔜 다음 계획

  • Addressables 기반 UI 로딩 (Resources 대체)
  • DOTween 연동 애니메이션 헬퍼
  • 네트워크 HTTP 헬퍼 (UniTask 기반)
  • 로컬라이제이션 시스템

이 Common 라이브러리는 Git 서브모듈로 관리하여 여러 프로젝트에서 공유합니다.
새 프로젝트를 시작할 때 git submodule add로 바로 가져다 쓸 수 있습니다.

🔄 업데이트 로그

2026-02-12: Coroutine → UniTask 전면 마이그레이션

  • UniTask 패키지 도입 (com.cysharp.unitask)
  • 코루틴 → async/await 전환: AudioHelper, BaseView, ScreenTransition, UIButtonExtensions
  • CancellationTokenSource 기반 취소 패턴 적용 (기존 StopCoroutine 대체)
  • CoroutineExtensions → UniTaskExtensions 전면 교체 (GetCancellationTokenOnDestroy() 기반 자동 취소)
  • WaitCache 삭제 — UniTask 자체 GC-free 대기 메서드로 대체
  • UIButtonExtensions 쿨다운에서 MonoBehaviour 런너 불필요해짐
반응형