1. UI 매니저 클래스 설계
- UIManager 클래스를 만들어 UI 요소를 관리.
- 해당 클래스는 싱글톤으로 디자인
- 제네릭 타입을 사용하여 여러 유형의 UI 요소를 관리
public class UIManager<T> where T : MonoBehaviour
{
private static UIManager<T> instance;
public static UIManager<T> Instance
{
get
{
if (instance == null)
{
instance = new UIManager<T>();
}
return instance;
}
}
// UI 요소를 관리하는 로직 추가
}
2. UI 프리팹 딕셔너리 사용
- UI 프리팹을 딕셔너리에 저장하여 동적으로 생성하거나 표시
public class UIManager<T> where T : MonoBehaviour
{
private Dictionary<string, T> uiPrefabs = new Dictionary<string, T>();
// UI 프리팹 등록
public void RegisterUIPrefab(string key, T prefab)
{
if (!uiPrefabs.ContainsKey(key))
{
uiPrefabs.Add(key, prefab);
}
}
// UI 생성
public T InstantiateUI(string key, Transform parent)
{
if (uiPrefabs.TryGetValue(key, out T prefab))
{
T instance = Object.Instantiate(prefab, parent);
return instance;
}
return null;
}
}
3. 이벤트 시스템 활용
- 옵서버 패턴을 사용하여 UI 갱신 및 상호 작용을 관리
- UI 갱신을 위해 이벤트를 발생시키고, 필요한 곳에서 해당 이벤트를 구독하여 UI를 업데이트
public class UIEventSystem
{
public static event Action<string> OnUIUpdate;
public static void TriggerUIUpdate(string uiKey)
{
OnUIUpdate?.Invoke(uiKey);
}
}
제네릭을 사용하면 함수나 클래스를 정의할 때 타입을 명시하지 않고, 나중에 사용될 때까지 일반적인 형식(T)으로 유지할 수 있다. 이는 코드의 유연성을 향상하고 중복 코드를 줄일 수 있다.
다음은 제네릭을 사용하지 않은 간단한 예제이다.
// 정수 형식만 다루는 클래스
public class IntProcessor
{
public int Process(int x, int y)
{
return x + y;
}
}
// 문자열 형식만 다루는 클래스
public class StringProcessor
{
public string Process(string x, string y)
{
return x + y;
}
}
그리고 위의 코드를 제네릭을 사용하여 개선하면 아래의 코드처럼 작성이 가능하다.
public class Processor<T>
{
public T Process(T x, T y)
{
return (dynamic)x + (dynamic)y;
}
}
여기서 'T'는 제네릭 형식 매개변수로, 나중에 사용될 때 실제 형식으로 대체된다. 이렇게 하면 Processor 클래스는 정수, 문자열 또는 다른 형식에 대해 동일한 기능을 수행할 수 있다.
제네릭은 특히 컬렉션과 같은 데이터 구조에서 많이 사용된다. 예를 들어, List<T> 나 Dictionary <TKey, TValue>와 같은 클래스들은 제네릭을 사용하여 여러 형식의 요소를 저장하고 다룰 수 있도록 한다.
또한 제네릭을 활용하면 다양한 유형의 컴포넌트나 기능을 일반화할 수 있다.
public class UIManager : Singleton<UIManager>
{
// Resources/Prefabs/UI 안의 UI 컴포넌트 프리팹들을 저장하는 딕셔너리
Dictionary<string, UI_Base> uiDic = new Dictionary<string, UI_Base>();
public T GetUIComponent<T>() where T : UI_Base
{
string key = typeof(T).Name;
if (!uiDic.ContainsKey(key))
{
// 요청 시점에 해당 UI 컴포넌트가 없다면 Load
var obj = Instantiate(Resources.Load($"Prefabs/UI/{key}"));
uiDic.Add(key, obj.GetComponent<T>());
}
return (T)uiDic[key];
}
public void RemoveUIComponent<T>() where T : UI_Base
{
string key = typeof(T).Name;
if (uiDic.ContainsKey(key))
{
uiDic.Remove(key);
}
}
}
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T _instance;
public static T Instance
{
get
{
if (_instance == null)
{
GameObject go = new GameObject(typeof(T).Name);
_instance = go.AddComponent<T>();
DontDestroyOnLoad(_instance);
}
return _instance;
}
}
}
public class UI_Base : MonoBehaviour
{
public virtual void OpenUI()
{
gameObject.SetActive(true);
}
public virtual void CloseUI()
{
gameObject.SetActive(false);
}
}