Humility

아무리 노력해도 최고가 되지 못할 수 있다⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀그럼에도 노력하는자가 가장 겸손한 것 아닌가

공부하는 블로그

유니티/디자인패턴

[Unity] 유니티 C#) 다양한 클래스 유형

새벽_글쓴이 2025. 1. 24. 12:33
반응형

 

공부를 하다보면 다양한 유형들의 클래스들이 있었다
이는 설계 원칙에 맞춰 만들어진 패턴이라 볼 수 있는데,
주로 사용되는 유형들에 대해 알아보았다

1. DTO (Data Transfer Object) 클래스

정의

순수하게 데이터만 담는 컨테이너 클래스

 

사용 시점

  • API 통신할 때 데이터 전송용
  • 데이터베이스에서 데이터 가져올 때
  • 다른 시스템과 데이터 교환할 때

 

예시

public class PlayerDTO
{
    public int id;
    public string name;
    // 데이터만 있고 메서드는 없음
}

2. 싱글톤 클래스

정의

전체 게임에서 단 하나의 인스턴스만 존재하는 클래스

 

사용 시점

  • 게임 전체 상태 관리 (GameManager)
  • 자원 공유 (ResourceManager)
  • 사운드 관리 (AudioManager)

 

예시

public class GameManager : MonoBehaviour // 게임에서 하나만 존재
{
    private static GameManager instance;
    public static GameManager Instance => instance;
    
    private void Awake() 
    {
        if (instance == null) instance = this;
        else Destroy(gameObject);
    }
    
    public void SaveGame() { /* 저장 로직 */ }
}

3. 컴포넌트 클래스

정의

GameObject에 붙여서 특정 기능을 수행하는 클래스

 

사용 시점

  • 캐릭터 움직임 구현
  • UI 요소 제어
  • 적 AI 구현

 

예시

// 행동 컴포넌트 - 플레이어 이동
public class PlayerMovement : MonoBehaviour 
{
    [SerializeField] private float speed = 5f;
    private Rigidbody rb;
    
    private void Update() 
    {
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");
        Vector3 movement = new Vector3(h, 0, v) * speed;
        rb.MovePosition(transform.position + movement * Time.deltaTime);
    }
}

// UI 컴포넌트 - 체력바
public class HealthBar : MonoBehaviour 
{
    [SerializeField] private Image fillImage;
    
    public void UpdateHealth(float currentHealth, float maxHealth) 
    {
        fillImage.fillAmount = currentHealth / maxHealth;
    }
}

4. 래퍼 클래스

정의

기존 클래스나 데이터를 감싸서 새로운 기능을 추가하는 클래스

 

사용 시점

  • 직렬화 불가능한 데이터 저장할 때
  • 외부 라이브러리 사용할 때
  • 복잡한 기능 단순화할 때

 

예시

// Dictionary 래퍼 (Dictionary는 직렬화 불가)
[System.Serializable] 
public class DictionaryWrapper<TKey, TValue>
{
   public TKey[] keys;
   public TValue[] values;
   
   public Dictionary<TKey, TValue> ToDictionary()
   {
       var dict = new Dictionary<TKey, TValue>();
       for(int i = 0; i < keys.Length; i++)
           dict.Add(keys[i], values[i]);
       return dict;
   }
}

// 네트워크 데이터 래퍼
[System.Serializable]
public class NetworkDataWrapper 
{
   public string dataType;
   public string jsonData;
   
   public T GetData<T>() where T : class
   {
       return JsonUtility.FromJson<T>(jsonData);
   }
}

// Unity 컴포넌트 래퍼
[System.Serializable]
public class TransformWrapper
{
   public Vector3 position;
   public Quaternion rotation;
   public Vector3 scale;
   
   public static TransformWrapper FromTransform(Transform t)
   {
       return new TransformWrapper
       {
           position = t.position,
           rotation = t.rotation,
           scale = t.localScale
       };
   }
}

// 이벤트 데이터 래퍼
[System.Serializable]
public class EventDataWrapper
{
   public string eventName;
   public string eventData;
   public float timestamp;
   
   public T ParseEventData<T>()
   {
       return JsonUtility.FromJson<T>(eventData);
   }
}

5. 유틸리티 클래스

정의

자주 사용하는 정적 메서드들을 모아놓은 클래스

 

사용 시점

  • 수학 계산
  • 문자열 처리
  • 파일 입출력

 

예시

// 헬퍼 - 유틸리티 함수 모음
public static class MathHelper 
{
    public static float CalculateDistance(Vector3 a, Vector3 b) 
        => Vector3.Distance(a, b);
    
    public static bool IsInRange(float value, float min, float max) 
        => value >= min && value <= max;
}

// 확장 메서드 - Transform 확장
public static class TransformExtensions 
{
    public static void ResetTransform(this Transform trans) 
    {
        trans.position = Vector3.zero;
        trans.rotation = Quaternion.identity;
        trans.localScale = Vector3.one;
    }
}

6. 인터페이스/추상클래스

정의

공통 기능을 정의하는 틀

 

사용 시점

  • 다양한 객체가 같은 기능을 구현할 때
  • 시스템 확장성이 필요할 때

 

예시

// 인터페이스 - 데미지 처리
public interface IDamageable 
{
    void TakeDamage(float damage);
    bool IsAlive { get; }
}

// 추상 클래스 - 무기 시스템
public abstract class Weapon : MonoBehaviour 
{
    protected float damage;
    protected float range;
    
    public abstract void Fire();
    protected virtual void Reload() { }
}

7. 이벤트 관련 클래스

정의

객체 간 통신과 상태 변화 알림을 처리하는 클래스

 

사용 시점

  • 객체의 상태 변화를 다른 객체에 알릴 때
  • UI 업데이트
  • 시스템 간 통신

 

예시

// 이벤트 아규먼트 - 피해 정보 전달
public class DamageEventArgs : EventArgs 
{
    public float Damage { get; private set; }
    public Vector3 HitPoint { get; private set; }
    
    // 이벤트 발생 시 전달할 데이터
    public DamageEventArgs(float damage, Vector3 hitPoint) 
    {
        Damage = damage;
        HitPoint = hitPoint;
    }
}

// 옵저버 패턴 - 체력 변경 통지
public class Health : MonoBehaviour 
{
	// 상태 변화를 구독자에게 알림
    public event Action<float> OnHealthChanged;
    private float currentHealth;
    
    public void TakeDamage(float damage) 
    {
        currentHealth -= damage;
        OnHealthChanged?.Invoke(currentHealth);
    }
}

// 사용 예시
public class Enemy : MonoBehaviour, IDamageable 
{
    private Health health;
    public bool IsAlive => health.CurrentHealth > 0;
    
    private void Start() 
    {
        health.OnHealthChanged += UpdateHealthUI;
    }
    
    public void TakeDamage(float damage) 
    {
        health.TakeDamage(damage);
    }
}

위처럼 사용하는 이유

1.코드 재사용성

공통 기능을 클래스로 분리하여 중복 코드 방지

예시
유틸리티 클래스로 자주 쓰는 함수 재사용

 

2. 유지보수성

기능별로 클래스 분리로 코드 관리 용이

예시
UI 로직과 게임 로직 분리

 

3. 확장성

인터페이스와 추상 클래스로 새로운 기능 쉽게 추가

예시
새로운 무기나 아이템 타입 추가
반응형