Skip to content

DragonTSpa/Unity-UI-Framework

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 

Repository files navigation

Unity UI Framework (Stack 기반 UIManager / UIView)

스택(Stack) 기반으로 화면 전환과 팝업을 관리하는 Unity UI 프레임워크입니다.
UIManagerUIView를 중심으로, 다음과 같은 요구사항을 해결하기 위한 구조입니다.

  • 씬 안의 여러 화면(뷰)을 일관된 규칙으로 전환하고 싶을 때
  • 전체 화면 전환과 팝업을 동일한 스택 위에서 다루고 싶을 때
  • 진입/퇴장 애니메이션을 프로필 기반으로 관리하고 싶을 때
  • UI GameObject의 활성/비활성/파괴까지 포함한 라이프사이클을 제어하고 싶을 때

폴더 구성

UIFramework/
  Components/
    UIManager.cs        // 스택 기반 UI 흐름 관리
    UIView.cs           // 개별 화면/팝업 단위 + 애니메이션/라이프사이클

  Core/
    ButtonAttribute.cs      // 인스펙터에서 메서드를 버튼으로 실행하기 위한 Attribute/Editor
    UIAnimationHelper.cs    // Slide / Zoom / Fade 코루틴 유틸
    UIEnums.cs              // UISlideDir, UIAnimType, UILifecycleMode 정의
    UITransitionProfile.cs  // 전환 설정 ScriptableObject

  Example/
    11.prefab               // 샘플 UIView 구성이 들어 있는 예제 프리팹
    UIViewTimingDebug.cs    // UIView 이벤트 타이밍 디버그용 스크립트

  Profiles/
      Default_UITransitionProfile.asset
      NoEnter.asset
      RightRight.asset
      UpDown.asset
      Zoom.asset

핵심 개념

1. Stack 기반 UI 흐름

UIManager는 내부에 Stack<UIView>를 가지고 있고,
현재 화면/팝업들의 상태를 “접시 쌓기”처럼 관리합니다.

  • Push(UIView view)
    • 일반 화면 전환
    • 현재 화면을 Hide() 한 뒤, 새 UIView를 스택에 Push + Show()
  • ShowPopup(UIView view)
    • 팝업 전환
    • 아래 화면은 유지한 채, 새 UIView를 스택에 Push + Show()
  • Pop()
    • 최상단 UIView를 Pop + Hide()
    • 그 아래 UIView가 있다면 다시 Show()를 호출해 복귀 연출
  • ClosePopup()
    • “팝업만 닫는” 용도
    • 최상단 UIView를 Pop + Hide()만 하고, 아래 UIView에는 Show()를 다시 호출하지 않음
    • 팝업 닫을 때 기존 전체 화면 진입 애니메이션이 다시 도는 버그를 방지
  • PopAll()
    • 스택에 쌓인 모든 UIView를 Pop 하면서 정리 (Hide()/ForceHide() 조합)
  • PopTo(UIView target)
    • 특정 UIView가 스택 어딘가에 있을 때, 그 지점까지 위에 있는 것들을 전부 Pop
    • 중간에 제거되는 뷰들은 ForceHide()로 즉시 정리하고, 타겟 뷰는 다시 Show()

요약하면:

  • Push = 새 화면을 위에 쌓는 동작
  • Pop / ClosePopup / PopTo / PopAll = 스택에서 내려가거나 정리하는 동작

으로 UI 흐름 전체를 하나의 스택 모델로 정리한 구조입니다.


2. UIView – 화면/팝업 1개의 단위

UIView는 Canvas 아래에 존재하는 하나의 화면/팝업 단위입니다.

[RequireComponent(typeof(RectTransform))]
[RequireComponent(typeof(CanvasGroup))]
[DisallowMultipleComponent]
public class UIView : MonoBehaviour
{
    [Header("Transition Profile (옵션)")]
    public bool overrideTransition = false;
    public UITransitionProfile profile;

    [Header("Override (overrideTransition=true 일 때만 유효)")]
    public UIAnimType entryAnim = UIAnimType.Slide;
    public UISlideDir entryDir = UISlideDir.Right;
    public float entrySpeed = 2f;

    public UIAnimType exitAnim = UIAnimType.Slide;
    public UISlideDir exitDir = UISlideDir.Left;
    public float exitSpeed = 2f;

    [Header("Lifecycle")]
    public UILifecycleMode lifecycle = UILifecycleMode.DeactivateOnHide;

    [Header("Events")]
    public UnityEvent onPreShow;
    public UnityEvent onPostShow;
    public UnityEvent onPreHide;
    public UnityEvent onPostHide;
}

주요 역할:

  • RectTransform / CanvasGroup 캐싱 및 제어
  • Show() / Hide() / ForceHide() 로 진입/퇴장 애니메이션과 라이프사이클 처리
  • onPreShow, onPostShow, onPreHide, onPostHide 이벤트 훅 제공
  • UILifecycleMode 값에 따라 Hide 이후 행동 결정
    • KeepActive : GameObject 활성 상태 유지
    • DeactivateOnHide : SetActive(false)
    • DestroyOnHide : Destroy(gameObject)

Show / Hide / ForceHide

  • Show()

    • GameObject를 활성화 (SetActive(true))
    • 최상단으로 올림 (transform.SetAsLastSibling())
    • Transition 설정(프로필/오버라이드)을 해석한 뒤, UIAnimationHelper를 통해
      • SlideIn / ZoomIn / FadeIn 중 하나를 코루틴으로 실행
    • CanvasGroup의 interactable, blocksRaycasts, alpha 를 적절히 세팅
    • onPreShow → 애니메이션 → onPostShow 순서로 이벤트 호출
  • Hide()

    • Transition 설정에 따라 SlideOut / ZoomOut / FadeOut 실행
    • CanvasGroup의 상호작용을 끄고(onPreHide) → 애니메이션 → onPostHide
    • 마지막에 ApplyLifecycle()로 GameObject 비활성/파괴 여부 결정
  • ForceHide()

    • 현재 진행 중인 애니메이션 코루틴을 즉시 중지
    • CanvasGroup을 바로 꺼주고(alpha=0 포함)
    • ApplyLifecycle()을 바로 적용해 애니 없이 즉시 정리

PopToPopAll처럼 “중간 화면들을 애니 없이 정리해야 하는 경우”에
ForceHide()가 사용됩니다.


3. Transition Profile (UITransitionProfile)

Core/UITransitionProfile.cs는 전환 설정을 ScriptableObject로 분리한 타입입니다.

[CreateAssetMenu(fileName = "UITransitionProfile", menuName = "UI/Transition Profile")]
public class UITransitionProfile : ScriptableObject
{
    [Header("Entry (Show)")]
    public UIAnimType entryAnim = UIAnimType.Slide;
    public UISlideDir entryDir = UISlideDir.Right;
    public float entrySpeed = 2f;

    [Header("Exit (Hide)")]
    public UIAnimType exitAnim = UIAnimType.Slide;
    public UISlideDir exitDir = UISlideDir.Left;
    public float exitSpeed = 2f;
}
  • UIAnimType : None, Slide, Zoom, Fade
  • UISlideDir : Left, Right, Up, Down, None

UIView.overrideTransition == false 일 때는 프로필 값을 사용하고,
overrideTransition == true일 때는 UIView 인스펙터에서 직접 지정한 값(entry/exit*)을 사용합니다.

Profiles/Transitions 폴더에는 샘플 프로필이 포함되어 있습니다.

  • Default_UITransitionProfile.asset
  • NoEnter.asset
  • RightRight.asset
  • UpDown.asset
  • Zoom.asset

프로젝트 스타일에 맞는 프로필을 복사/수정해서 사용하면 됩니다.


4. UIAnimationHelper – 애니메이션 유틸

UIAnimationHelper는 실제 애니메이션을 수행하는 정적 유틸 클래스입니다.

주요 메서드(일부):

  • IEnumerator SlideIn(RectTransform rect, UISlideDir dir, float speed, UnityAction onEnd)
  • IEnumerator SlideOut(RectTransform rect, UISlideDir dir, float speed, UnityAction onEnd)
  • IEnumerator ZoomIn(RectTransform rect, float speed, UnityAction onEnd)
  • IEnumerator ZoomOut(RectTransform rect, float speed, UnityAction onEnd)
  • IEnumerator FadeIn(CanvasGroup group, float speed, UnityAction onEnd)
  • IEnumerator FadeOut(CanvasGroup group, float speed, UnityAction onEnd)

UIView는 내부에서 이 코루틴들을 사용해 전환 애니메이션을 처리합니다.


5. ButtonAttribute – 인스펙터 실행용 버튼

Core/ButtonAttribute.cs는 에디터 전용 Attribute입니다.

  • 메서드 위에 [Button("라벨명")] 을 붙이면,
    인스펙터에서 해당 메서드를 버튼 클릭으로 실행할 수 있습니다.
  • UIManager / UITransitionProfile에 예제가 포함되어 있습니다.
    • UIManager.Editor_PrintViewStack()
    • UIManager.Editor_ResetToDefaults()
    • UITransitionProfile.Editor_ResetToDefaults()

게임 실행 중에도 인스펙터에서 바로 호출할 수 있어, 디버깅/초기화에 유용합니다.


6. Example – UIViewTimingDebug

Example/UIViewTimingDebug.cs는 UIView 이벤트 타이밍을 로그로 보는 샘플입니다.

  • DebugTime1() → OnPreShow에 연결
  • DebugTime2() → OnPostShow에 연결
  • DebugTime3() → OnPreHide에 연결
  • DebugTime4() → OnPostHide에 연결

이 스크립트를 UIView 하위 오브젝트에 붙이고,
UIView의 UnityEvent에 연결하면 애니메이션 진행 순서를 쉽게 확인할 수 있습니다.


사용 방법

1) UIManager 배치

  1. Canvas 아래에 빈 GameObject를 만들고 UIManager 컴포넌트를 붙입니다.
  2. uiRoot 에는 UIView들이 붙을 기준 RectTransform을 지정합니다.
    (보통 Canvas의 메인 패널)
  3. 처음에 표시할 UIView를 initialView 에 할당합니다.
  4. showInitialOnStart 를 켜두면, Start()에서 자동으로 ResetAndPush(initialView) 가 호출됩니다.

2) UIView 생성

  1. Canvas 아래에 Panel UI를 하나 만들고, 그 루트에 UIView를 붙입니다.
  2. CanvasGroup이 자동으로 요구되므로, 없으면 추가합니다.
  3. 레이아웃/버튼/텍스트 등 화면 구성을 하고,
  4. 전환 방식을 정합니다.
    • 공통 프로필 사용: overrideTransition = false, profile 지정
    • 개별 설정 사용: overrideTransition = true, entry/exit 관련 필드 직접 설정
  5. Hide 이후 라이프사이클을 선택합니다.
    • 자주 다시 보여줄 화면 → DeactivateOnHide
    • 일회성 팝업 → DestroyOnHide

3) 버튼에서 전환 호출 예시 (스크립트 방식)

using UnityEngine;

public class SampleUIEntry : MonoBehaviour
{
    [SerializeField] private UIManager uiManager;
    [SerializeField] private UIView lobbyView;
    [SerializeField] private UIView popupView;

    public void OnClick_GoLobby()
    {
        uiManager.ResetAndPush(lobbyView);
    }

    public void OnClick_OpenPopup()
    {
        uiManager.ShowPopup(popupView);
    }

    public void OnClick_Back()
    {
        uiManager.Pop();
    }

    public void OnClick_ClosePopup()
    {
        uiManager.ClosePopup();
    }
}

버튼의 OnClick 이벤트에 위 메서드들을 연결해서 사용하면 됩니다.
(혹은, 버튼 OnClick에서 직접 UIManager GameObject를 참조해 Push/ShowPopup/Pop/ClosePopup을 호출해도 됩니다.)

4) 초기 화면을 애니메이션 없이 띄우고 싶을 때

  • UIView의 entry 애니메이션을 UIAnimType.None으로 설정하거나,
  • NoEnter 같은 프로필(asset)을 만들어 entryAnim을 None으로 지정한 뒤,
    초기 뷰에 해당 프로필을 연결하면 됩니다.

이렇게 하면 첫 진입 시에는 애니 없이 바로 그려지고,
이후 다른 화면에서 다시 Push될 때는 원하는 전환 애니메이션을 쓸 수 있습니다.


정리

이 UI 프레임워크는 다음을 목표로 합니다.

  1. 스택 기반으로 화면 전환과 팝업을 단일 규칙으로 관리
  2. UIView 단위로 전환 애니메이션 + 라이프사이클 책임 분리
  3. ScriptableObject 프로필을 통한 전환 설정 재사용
  4. ButtonAttribute/Debug 스크립트를 통한 에디터 친화적인 디버깅 지원

필요에 따라 Addressables, ViewId 매핑, 상태 저장(탭/스크롤 위치) 등을 추가해
자기 프로젝트 스타일에 맞는 UI 시스템으로 확장해서 사용할 수 있습니다.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages