유니티/멋쟁이사자처럼
[멋쟁이 사자처럼 부트 캠프 TIL 회고] Unity 게임 개발 3기 - 디자인 패턴 이란?
몰캉이이
2025. 1. 1. 17:48
디자인 패턴
목차
1. 기본 개념
게임 개발 과정에서 자주 발생하는 문제들을 해결하기 위한 재사용 가능한 솔루션
- 코드의 재사용성 향상
- 유지보수 용이성
- 확장성 개선
- 협업 효율화
2. 핵심 디자인 패턴
1. Singleton
더보기
public class GameManager : MonoBehaviour
{
private static GameManager instance;
public static GameManager Instance
{
get {
if (instance == null)
{
instance = FindObjectOfType<GameManager>();
if (instance == null)
{
GameObject go = new GameObject("GameManager");
instance = go.AddComponent<GameManager>();
}
}
return instance;
}
}
void Awake()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(gameObject);
}
else if (instance != this)
{
Destroy(gameObject);
}
}
}
2. Observer
더보기
public class EventManager
{
private Dictionary<string, Action<object>> eventDictionary = new Dictionary<string, Action<object>>();
public void Subscribe(string eventName, Action<object> listener)
{
if (!eventDictionary.ContainsKey(eventName))
{
eventDictionary[eventName] = null;
}
eventDictionary[eventName] += listener;
}
public void Unsubscribe(string eventName, Action<object> listener)
{
if (eventDictionary.ContainsKey(eventName))
{
eventDictionary[eventName] -= listener;
}
}
public void TriggerEvent(string eventName, object data)
{
if (eventDictionary.ContainsKey(eventName))
{
eventDictionary[eventName]?.Invoke(data);
}
}
}
3. State
더보기
public interface IPlayerState
{
void Enter();
void Update();
void Exit();
}
public class IdleState : IPlayerState
{
private Player player;
public IdleState(Player player)
{
this.player = player;
}
public void Enter()
{
player.Animator.Play("Idle");
}
public void Update()
{
// Check for state transitions
if (Input.GetKeyDown(KeyCode.Space))
{
player.ChangeState(new JumpState(player));
}
}
public void Exit()
{
// Cleanup code
}
}
public class Player : MonoBehaviour
{
private IPlayerState currentState;
public Animator Animator { get; private set; }
public void ChangeState(IPlayerState newState)
{
currentState?.Exit();
currentState = newState;
currentState.Enter();
}
void Update()
{
currentState?.Update();
}
}
4. Command
더보기
public interface ICommand
{
void Execute();
void Undo();
}
public class MoveCommand : ICommand
{
private Transform transform;
private Vector3 direction;
private float speed;
private Vector3 previousPosition;
public MoveCommand(Transform transform, Vector3 direction, float speed)
{
this.transform = transform;
this.direction = direction;
this.speed = speed;
}
public void Execute()
{
previousPosition = transform.position;
transform.Translate(direction * speed * Time.deltaTime);
}
public void Undo()
{
transform.position = previousPosition;
}
}
3. Unity 특화 패턴
1. Component
더보기
public class Health : MonoBehaviour
{
[SerializeField] private float maxHealth = 100f;
private float currentHealth;
void Start()
{
currentHealth = maxHealth;
}
public void TakeDamage(float damage)
{
currentHealth -= damage;
if (currentHealth <= 0)
{
Die();
}
}
private void Die()
{
// Death logic
}
}
2. Object Pool
더보기
public class ObjectPool : MonoBehaviour
{
[System.Serializable]
public class Pool
{
public string tag;
public GameObject prefab;
public int size;
}
public List<Pool> pools;
public Dictionary<string, Queue<GameObject>> poolDictionary;
void Start()
{
poolDictionary = new Dictionary<string, Queue<GameObject>>();
foreach (Pool pool in pools)
{
Queue<GameObject> objectPool = new Queue<GameObject>();
for (int i = 0; i < pool.size; i++)
{
GameObject obj = Instantiate(pool.prefab);
obj.SetActive(false);
objectPool.Enqueue(obj);
}
poolDictionary.Add(pool.tag, objectPool);
}
}
public GameObject SpawnFromPool(string tag, Vector3 position, Quaternion rotation)
{
if (!poolDictionary.ContainsKey(tag))
return null;
GameObject objectToSpawn = poolDictionary[tag].Dequeue();
objectToSpawn.SetActive(true);
objectToSpawn.transform.position = position;
objectToSpawn.transform.rotation = rotation;
poolDictionary[tag].Enqueue(objectToSpawn);
return objectToSpawn;
}
}
4. 패턴 선택 가이드
1. Singleton
- 글로벌 상태 관리가 필요할 때
- 리소스 관리자가 필료할 때
2. Observer
- 시스템 간 결합도를 낮추고 싶을 때
- 이벤트 기반 시스템 구현 시
- UI 업데이트 처리 시
3. State
- 복잡한 상태 전이가 필요할 때
- 캐릭터 행동 관리 시
- 게임 플로우 제어 시
4. Object Pool
- 빈번한 생성/파괴가 있는 객체 처리 시
- 파티클 시스템 구현 시
- 총알이나 적 캐릭터 스폰 시
5. 주의 사항
1. 과도한 패턴 사용 피하기
- 필요한 곳에만 적절한 패턴 적용
- 코드 복잡도 증가 고려
2. 성능 고려
- 패턴 적용으로 인한 오버헤드 확인
- 최적화 필요설 검토
3. 유지보수성
- 문서화 중요
- 팀원들과의 커뮤니케이션