게임 프로그래밍의 7가지 디자인 패턴

고현규·2023년 12월 1일

1. 싱글톤 패턴(Singleton Pattern)

  • 특정 클래스의 인스턴스가 딱 하나만 존재하도록 보장하는 패턴
    딱 한번만 생성되고 사라진다.
  • 클래스의 인스턴스를 전역적으로 접근이 가능
  • 프로그램의 생명주기동안 이 인스턴스는 한 번만 생성됨.
  • 전역 변수보다 안전함

전역변수는 게임이 실행이 되는 순간에 시작하자마자 변수가 생성되지만,
싱글톤으로 구현하면 클래스가 생성되는 시점을 개발자가 결정할 수 있다.
따라서 메모리적으로 중요한 패턴이다.
또한, 클래스 자체를 엉키지 않고 깔끔하게 관리할 수 있다.

사용처

게임의 설정, 오디오 매니저, UI 매니저

단점

  • 클래스 사이의 의존성이 높아진다
  • private 생성자 때문에 상속이 어렵다.
  • 단위 테스트하기가 힘들다.

2. 상태 패턴

  • 객체의 상태에 따라 객체의 행동을 변경한다.
  • 조건문이 아니라 객체의 상태를 별도의 클래스로 캡슐화
  • 객체는 runtime에 자신의 행동을 변경한다.

유저들은 각각의 상태가 있다.
상태를 클래스로 구현하고, 그것을 오브젝트에 넣어 움직이게 한다
게임 캐릭터가 상태가 굉장히 많으면 상태만 추가하면 되서 편하다.


3. 관찰자 패턴(Observer Pattern)

  • 한 객체의 상태 변화를 관찰하는 다수의 객체
  • 주인공 객체가 변하면 관찰자들에게 자동으로 알려줌
  • 상태 변화에 따른 자동 업데이트 (구독 시스템과 유사)
  • 객체들 사이의 의존성을 줄이고, 정보를 적절히 공유하는 형태

플레이어의 체력이 바뀐다던가 점수를 획득한다는 이벤트들이 발생 했을 때
시스템이 반응을 해야할 때 그것들이 한꺼번에 반응할 때 유용하다.

단점

  • 등록한 관찰자를 삭제할 때 removeObserver()와 같은 일련의 처리를 하지 않으면 불필요한 퍼포먼스 낭비가 일어날 가능성이 있다.

  • 각동시에 A와 B라는 이벤트가 발생했을 때 A와 B가 서로의 상태에 따라 각기 다른 처리를 하도록 참조된 경우 해당 이벤트의 처리 순서에 따라 결과가 달라지는 상황이 생길 수 있다.

  • 프로그램에서 코드가 서로 어떻게 상호작용하는지를 알기가 어렵기 때문에 런타임 때에 디버그를 걸어서 확인해야 하는 상황이 생길 수 있다.


4. 커맨드 패턴(Command Pattern)

  • 유저의 입력을 다룰 때 많이 사용하는 패턴
  • 요청을 객체의 형태로 캡슐화 한다.
  • 요청 코드와, 수행 코드사이의 의존성을 줄인다.
  • 입력 처리를 깔끔하고 유연하게 관리하고, 명령을 추가하거나 재사용이 쉬워짐

일종의 TV와 리모컨의 관계. 리모컨 버튼 하나하나를 클래스로 만들어진다.
버튼을 누르는것과 어떻게 반응하는지를 분리하는 패턴이다.

입력처리를 깔끔하게 구현할 수 있고, 행동은 따로 구현할수 있다.


5. 컴포넌트 패턴(Component Pattern)

  • 객체의 행동을 작은 부품(컴포넌트)으로 분리
  • 부품을 조합하여 복잡한 동작을 구현
  • 게임 캐릭터를 레고 조립하듯이 구성한다.
  • 개별 컴포넌트를 재사용하여 개발시간을 줄이고, 유지보수를 쉽게 만든다

게임의 정석같도 같은데 복잡한것들 레고 조립하듯이 부품을 나눠 조립하는 것으로 만든다.
협업에 필수적이다. 이렇게 구현을 해야만 일도 나누고 시간을 줄일 수 있다.

예를들어, 컴포넌트 클래스를 인터페이스를 만들고
이동하는 클래스, 점프하는 클래스 등등 생성한 뒤

게임 오브젝트에 컴포넌트를 리스트로 다 추가한다.


6. 빌더 패턴(Builder Pattern)

  • 복잡한 객체의 생성 과정을 단계별로 분리
  • 객체의 생성과 표현을 분리하는 것
  • 생성하는 과정에서 서로 다른 표현을 가진 객체를 만드는 것
  • 복잡한 게임 오브젝트나 레벨을 생성할 때 사용 됨. (캐릭터나 맵 등)

샌드위치 조립기와 같은 느낌이다.
이 빌더는 커다란 제조기가 빌더고 어떻게 찍어내냐 따라에 표현하는 클래스가 달라진다.

게임에서는 복잡한 패턴이나 난이도 조절.
몬스터 개수라던가 하나의 맵을 찍을 때 형태가 조금씩 다를 때

빌드 파트 A B C 인터페이스로 있으면
A는 모델, B는 애니메이션, C는 캐릭터 능력치를 찍어서 하나로 합쳐서 만든다.
내용 구성은 해당 빌더 안에서 구현해두면 된다.

7. 플라이웨이트 패턴(Flyweight Pattern)

  • 메모리 사용을 최적화하기 위한 패턴
  • 객체의 공유를 촉진하는 형태.
  • 플라이웨이트 패턴 상태 종류
    • 변경 불가능한 공유 상태
    • 객체마다 다를 수 있는 개별 상태
  • 공유 상태는 객체 내부에 저장. 개별 상태는 클라이언트에 의해 관리됨
  • 도서관에서 책을 빌리는 것.
    • 책은 공유 객체
    • 각 사람은 책을 보며 개별적으로 필기하면서 정보를 관리할 수 있음.
  • 대규모 게임 환경에서 반복되는 아이템을 관리할 때 유용함. 모바일 게임에서도 유용

핵심은 메모리 사용을 최적화 한다.

한정된 수량의 책을 빌린다.
볼 사람들은 보고 그곳에 필기를 하면 이를 모두가 같이 공유한다.

예시로 와우로 들자면
전역 퀘스트 아이템이 있으면 퀘스트 하는사람마다 똑같은 아이템을 하나씩 써야하는데
누가 사용했냐 따라 퀘스트 진행 수준이 달라진다.
대규모 게임 환경에서 반복되는 아이템 등에 사용된다.

나무를 예시로 들면 대규모 맵에 나무를 엄청 심어야한다
매번 나무마다 각 모델과 텍스처를 불러오면 낭비가 되기 때문에
모든 나무가 공유하는 텍스터는 모두가 공유하고
나무의 위치를 따로 두어 나무를 여러개 관리할 수 있게 된다.


디자인 패턴의 적절한 사용

너무 디자인 패턴에 집착해서는 안된다.
애초에 디자인 패턴은 특정 문제를 해결하기 위해 고려된 것이다.

  • 성능과 메모리 사용
  • 재사용성과 확장성 고려

너무 남발하면 코드가 안좋아질 수 있다.
디자인 패턴은 좋은 도구이지만, 모든 상황에 억지로 사용하면 오히려 코드가 복잡해진다.

무엇보다 팀원간의 소통이 필요하다.
본인만의 혼자 생각으로 패턴을 사용해서 구현을 하고 있는데
팀원이 이해를 못하면 문제가 발생할 수 있다
시작할 때 패턴을 정해두고 넘어가자.

profile
게임 개발과 기획

0개의 댓글