Files
XRLib/Assets/Scripts/UVC/core/Singleton.cs
2025-06-10 20:16:35 +09:00

250 lines
7.6 KiB
C#

using System;
using UnityEngine;
namespace UVC.Core
{
#region Singleton
/// <summary>
/// MonoBehaviour가 아닌 일반 클래스를 위한 싱글톤 패턴
/// 지연 초기화(lazy initialization)를 사용하여 필요할 때만 인스턴스 생성
/// </summary>
/// <typeparam name="T">싱글톤으로 구현할 클래스 타입(반드시 기본 생성자가 있어야 함)</typeparam>
/// <example>
/// <code>
/// public class JournalClass
/// {
/// // 클래스 내용
/// }
///
/// // 싱글톤 사용 예시
/// var journalSingleton = Singleton<JournalClass>.Instance;
/// </code>
/// </example>
public class Singleton<T> where T : class, new()
{
/// <summary>
/// 싱글톤 인스턴스를 지연 초기화 방식으로 생성
/// </summary>
protected static readonly Lazy<T> instance = new Lazy<T>(() => new T());
/// <summary>
/// 외부에서 생성자 직접 호출 방지
/// </summary>
protected Singleton(){}
/// <summary>
/// 싱글톤 인스턴스에 접근하기 위한 전역 접근점
/// </summary>
/// <example>
/// <code>
/// // 싱글톤 인스턴스 접근 방법
/// MyClass instance = Singleton<MyClass>.Instance;
/// </code>
/// </example>
public static T Instance { get { return instance.Value; } }
}
#endregion
#region SingletonApp
/// <summary>
/// 씬 전환 시에도 유지되는 MonoBehaviour 기반 싱글톤
/// DontDestroyOnLoad를 통해 씬 전환 시에도 객체가 파괴되지 않음
/// </summary>
/// <typeparam name="T">MonoBehaviour를 상속받는 컴포넌트 타입</typeparam>
/// <example>
/// <code>
/// // 사용 예시
/// public class AppMain : SingletonApp<AppMain>
/// {
/// protected override void Init()
/// {
/// // 초기화 코드 작성
/// ULog.Debug("AppMain 초기화 완료");
/// }
/// }
///
/// // 접근 방법
/// AppMain.Instance.SomeMethod();
/// </code>
/// </example>
public abstract class SingletonApp<T> : UnityEngine.MonoBehaviour where T : UnityEngine.Component
{
/// <summary>
/// 싱글톤 인스턴스
/// </summary>
private static T instance;
/// <summary>
/// 싱글톤 인스턴스에 접근하기 위한 전역 접근점
/// 인스턴스가 없는 경우 자동으로 생성함
/// </summary>
/// <example>
/// <code>
/// // 접근 방법
/// MyAppSingleton.Instance.DoSomething();
/// </code>
/// </example>
public static T Instance
{
get
{
if (instance == null)
{
instance = (T)GameObject.FindFirstObjectByType(typeof(T)); // Updated to use FindFirstObjectByType
if (instance == null)
{
// 씬에 인스턴스가 없으면 새로 생성
instance = new GameObject(string.Format(typeof(T) + "")).AddComponent<T>();
}
}
return instance;
}
}
/// <summary>
/// 컴포넌트가 활성화될 때 호출되는 Unity 메소드
/// 인스턴스 설정 및 씬 전환 시 객체 유지 설정
/// </summary>
protected virtual void Awake()
{
if (instance == null)
{
instance = this as T;
}
// 인스턴스 초기화 호출
(instance as SingletonApp<T>).Init();
//if (transform.parent != null && transform.root != null)
//{
// DontDestroyOnLoad(transform.root.gameObject);
//}
//else
{
// 씬 전환 시에도 파괴되지 않도록 설정
DontDestroyOnLoad(gameObject);
}
}
/// <summary>
/// 인스턴스화될 때 호출되는 초기화 메소드
/// 자식 클래스에서 오버라이드하여 초기화 로직 구현
/// </summary>
/// <example>
/// <code>
/// protected override void Init()
/// {
/// // 초기화 코드 작성
/// playerData = new PlayerData();
/// LoadSettings();
/// }
/// </code>
/// </example>
protected virtual void Init() { }
}
#endregion
#region SingletonScene
/// <summary>
/// 현재 씬 내에서만 유지되는 MonoBehaviour 기반 싱글톤
/// 씬 전환 시 인스턴스가 파괴됨
/// </summary>
/// <typeparam name="T">MonoBehaviour를 상속받는 컴포넌트 타입</typeparam>
/// <example>
/// <code>
/// // 사용 예시
/// public class SceneMain : SingletonScene<SceneMain>
/// {
/// protected override void Init()
/// {
/// // 초기화 코드 작성
/// ULog.Debug("SceneMain 초기화 완료");
/// }
/// }
///
/// // 접근 방법
/// SceneMain.Instance.SomeMethod();
/// </code>
/// </example>
public abstract class SingletonScene<T> : UnityEngine.MonoBehaviour where T : UnityEngine.Component
{
/// <summary>
/// 싱글톤 인스턴스
/// </summary>
private static T instance;
/// <summary>
/// 싱글톤 인스턴스에 접근하기 위한 전역 접근점
/// 인스턴스가 없는 경우 자동으로 생성함
/// </summary>
/// <example>
/// <code>
/// // 접근 방법
/// MySceneSingleton.Instance.DoSomething();
/// </code>
/// </example>
public static T Instance
{
get
{
if (instance == null)
{
instance = (T)GameObject.FindFirstObjectByType(typeof(T)); // Updated to use FindFirstObjectByType
if (instance == null)
{
// 씬에 인스턴스가 없으면 새로 생성
instance = new GameObject(string.Format(typeof(T) + "")).AddComponent<T>();
}
}
return instance;
}
}
/// <summary>
/// 컴포넌트가 활성화될 때 호출되는 Unity 메소드
/// 인스턴스 설정 및 초기화
/// </summary>
protected virtual void Awake()
{
if (instance == null)
{
instance = this as T;
}
// 인스턴스 초기화 호출
(instance as SingletonScene<T>).Init();
}
/// <summary>
/// 인스턴스화될 때 호출되는 초기화 메소드
/// 자식 클래스에서 오버라이드하여 초기화 로직 구현
/// </summary>
/// <example>
/// <code>
/// protected override void Init()
/// {
/// // 초기화 코드 작성
/// uiManager = GetComponent<UIManager>();
/// SetupEventListeners();
/// }
/// </code>
/// </example>
protected virtual void Init() { }
/// <summary>
/// 컴포넌트가 파괴될 때 호출되는 Unity 메소드
/// 싱글톤 인스턴스 참조 해제
/// </summary>
protected virtual void OnDestroy()
{
instance = null;
}
}
#endregion
}