이문회우

게임 프로그래밍 패턴 본문

게임 프로그래밍 패턴

Koesob 2023. 4. 20. 16:08

드디어 끝냈다!

 

끝낸 기념 정리


디자인 패턴 다시 보기

1. 명령

- 다양한 형태로 존재하는 것은 단일한 형태로 감싸면 좋다. 이것은 이 책 내내 반복돼서 나온다.

 

2. 경량

- 공유할 수 있는 것은 공유하자. 다만 포인터를 직접적으로 쓸 수 있는 C++에서 큰 의미를 갖지 포인터를 쓰지 않는 C#에서는 구현이 복잡해질 것 같은 느낌

 

3. 관찰자

- 요새 프로젝트 진행 때마다 항상 나오는 화두인 이벤트 옵저버-리스너.

- 개인적으로는 막 쓰고 싶지는 않은 디자인 패턴이다. 직관적이지 않은 경우 코드 읽기가 너무 어려움.

- 이 책에서는 응집성을 높일 필요가 있는 쪽에서는 그냥 커플링을 만드는게 낫다고 한다.

 

4. 프로토타입

- 프로토타입 '패턴'을 설명보다는 프로그래밍 언어 '패러다임'으로서 프로토타입을 더 설명했다.

- 위임이 핵심. 근연 관계가 아니어도 상관 없다.

'내 정보 말인가? 원한다면 주마. 어디 찾아봐라! 이 객체의 정보를 그 곳에 두고 왔으니!'

- 찾으려는 정보가 A에게 없을 경우, A의 프로토타입으로 지정된 B에서 찾아본다. 마찬가지로, B에게도 없을 경우, B의 프로토타입으로 지정된 C에게 찾아본다. 상속과는 다르다. A는 캐릭터 클래스, B는 총알 클래스, C는 맵 클래스일 수도 있다.

- 한 편, 자신을 프로토타입으로 하는 또 다른 객체를 만드는 Clone도 특징이라면 특징. 

 

5. 싱글턴

- 얘는 관찰자 패턴보다 약간 1~2년 전 유행한 듯한 느낌(?)의 디자인 패턴

- 처음에는 '오... 너무 신기하다' 하면서 썼지만, 실상 전역 변수랑 다를바 없이 쓰는 느낌도 있음.

- 책에서도 싱글턴 사용의 남용을 자제하라고 말하며 싱글턴은 단 한 개, 그리고 그 싱글턴이 여러 클래스의 인스턴스를 갖는 식으로 싱글턴을 획기적으로 줄이는 방법을 제안한다.

- 특히 저 방법을 말할 때, 'Manager' 예시를 직접적으로 언급한다. '당신의 안녕을 위하여'가 딱 저 구조로 돼 있다.

- 하나의 'Manager' 싱글턴. 그리고 그것이 각각의 역할을 담당하는 Manager 인스턴스를 갖고 있다. 어차피 Manager가 하나니까 Manager 인스턴스도 하나로 보장됨.

- 아마도 프레임워크 영향을 끼친 루키스 그 분도 이 내용을 알고 계셨던듯?

- 한 편으로는 그냥 단일 클래스 관리용(즉, Manager)으로만 싱글턴 만들거면 각 클래스가 자기 자신을 관리하게 만들라고 한다. 그게 객체 지향이라고. 맞는 말이긴 해.

 

6. 상태

- 각각의 경우를 확인하기 위해 끊임없이 bool 플래그 세우지 말고, 상태로 묶어라.

- FSM으로 유명하다. 유니티에서는 애니메이션 작업할 때 많이 접한다.

- 오토마타 이론과 연관 지어 설명한다. 오토마타가 뭐냐고? 나무위키를 참고하자. 꽤 재밌는 분야다.

- 최근에 드는 생각이 현실을 반영하도록 코드를 구현해야하지 않나-라는게 있었는데 이 상태 패턴이 가장 비슷하지 않나 싶다.

 

순서 패턴

- 이 파트는 게임을 만든다기보단 '게임 엔진을 만든다'에 가깝다.

- 달리 말하면 꽤 스킵하면서 읽었다.

1. 이중 버퍼

- 어떻게 하면 한 프레임에서 이뤄져야 할 일들을 한 방에 보여줄 수 있나

→ 1) 지금 프레임에 이뤄져야할 것들 등록 2) 다음 프레임에 이뤄져야할 것들 싹 미리 등록

→ 다음 프레임 때, 2)로 전환.

- 포인터를 사용할 수 있을 때 일리가 있단 느낌?

 

2. 게임 루프

- 스킵

 

3. 업데이트 메서드

- 스킵

행동 패턴

1. 바이트코드

- 카드 게임을 한다치자. 매 번 새로운 효과를 코딩으로 짜넣을 것인가? 그럼 테스트할 때마다 빌드해야함?

- 이런 문제에 대한 해결책으로 보면 된다.

- 게임을 만들 때, 각 행동, 예를 들면 '체력 회복, 카드 1장 뽑기' 이런 행동들을 실행하는 커맨드를 만들어둔다.

- 기획자는 그 커맨드를 바꾸는 식으로 효과를 만들어내고, 게임은 그저 그 커맨드를 읽어내려가는 것만으로 동작한다. 그러면 빌드가 필요치 않음

- '당신의 안녕을 위하여'가 어느정도 이 형식을 띄고 있다. 기능만 준비를 해두고 CSV에서 기획자가 그 기능을 적어두면, 게임이 실행하면서 CSV를 읽으며 각 동작을 수행하는 식으로.

- 롤도 이런 식이겠구나 무릎을 탁! 쳤다. 대신에 새로운 챔피언을 출시할 때마다 이 커맨드가 하나씩 늘어나는거지.

- 최근에 카드 게임을 만들고 있는데 이 때 효과를 어떻게 처리해야하나- 고민하던 차에 도움이 많이 된 파트.

 

2. 하위 클래스 샌드박스

- 1번 바이트코드랑 맥락은 비슷하다. 다만 1번이 프로그래머 - 기획자 간의 관계라고 한다면, 이것은 클래스에서의 바이트코드다. 부모 클래스에서 각 기능용 함수들을 만들어두고, 자식 클래스에서는 그 기능을 호출한다.

- 부모가 샌드박스임

 

3. 타입 객체

- 몬스터 타입과 같이 여러 종류를 필요하는 경우, 종류별로 여러 자식 클래스를 만드는 것이 아니라, 몬스터 클래스 단 하나만 만들어두고 내부 특성만 외부의 기획 파일(JSON이 대표적)을 읽어오는 식으로 구현한다.

- 1번과 2번 기능을 혼합하면 괜찮을지도.

- 1,2,3 모두 비슷한 맥락일지도 모르겠다.

디커플링 패턴

1. 컴포넌트

- 유니티 근본 기능이라 익숙

- 다른 기능들과는 확실히 구분된다면 해당 기능을 '컴포넌트'로 분리한다.

- 그렇게 모든 기능들이 컴포넌트 단위로 분리가 된다면, 게임 속 오브젝트는 여러 컴포넌트를 갖고 있는 껍데기 같은 것이 된다.

- 기능 자체는 익숙하고, 컴포넌트 간 통신이 이슈인데 필요하다면 커플링도 얼마든지. 한 편 이를 위해 이벤트 큐를 쓸 수도

 

2. 이벤트 큐

- 게임 시스템 내 여러 클래스들이 서로 요청을 하고, 그 요청에 대해 즉각적으로 실행이 이뤄지다보면 시스템이 꼬일 수 있다.

- 따라서 요청과 처리를 분리한다. 소통 창구 같은 곳. 그곳이 이벤트 큐이다.

- 요청이 한 곳으로 모이면, 이벤트 큐는 그것을 규칙에 따라 차근차근 실행한다.

- '당신의 안녕을 위하여'가 대략 이런 식이다. 기획자가 CSV에 적어둔 내용을 쫙 읽어들인다. 그리고 그 내용을 시스템적 기능으로 변환을 해서 이벤트 '스택'에 쌓아두고 차근차근 실행을 하는데, 실행 과정 중에서도 다시 요청이 발생할 수 있고 그것은 다시 스택에 쌓인다. 그런식으로 스택을 다 비울 때까지 동작들을 처리해나간다.

- 패턴 설명은 '큐'인데 당신의 안녕을 위하여는 '스택' 구조다. 뭐 이건 필요에 따라 변할 수 있지

 

3. 서비스 중개자

- 각 기능과는 독립적이면서 자주 사용되는 기능은 하나로 묶어서 어떤 곳에서든 사용할 수 있게 한다(?)

- 메이플스토리 월드에서 이 '서비스' 패턴을 제공해서 이해를 하는데에는 쉬웠다.

- 물론 당시에는 내가 이 개념이 없어서 좀 엉망진창으로 사용함. 서비스에다가 정보를 저장한다든지...

최적화 패턴

- 이 파트는 메모리, 컴퓨터 구조, 운영체제에 대한 이해, 자료구조의 중요성을 논한 챕터다. 즉, 재미 없어서 슥슥 넘기면서 봄

- 자료구조를 써야 Hit 비율을 늘릴 수 있습니다! 딱 그 느낌.

- 무슨 말인지 모르겠다면 운영체제를 배우면 된다. ㅎ;

1. 데이터 지역성

- 함께 자주 사용하는 데이터들은 자료구조로 묶어주자.

- 이 파트가 딱 운영체제에서 배운 내용을 설명한다. 이것도 패턴인가? 싶은 느낌도 있었음

2. 더티 플래그

- 스킵

3. 객체 풀

- 오브젝트 풀링. 아마 다음 프로젝트 화두가 되지 않을까

- 스킵

4. 공간 분할

- 주변에 어떤 객체가 있는가?를 확인하기 위해서 모든 객체의 위치를 확인하는 것은 코스트가 너무 크다.

- 맵을 여러 구역으로 나눈다. 모든 객체를 확인하는 것이 아니라, 해당 객체가 있는 구역과 주변 구역만 탐색한다.


책 자체의 내용은 음...

- IT책 특유의 친근한척 하는 문체. 알 사람은 알듯

- 친근한척 한다 했지 내용과 친해지게 해주는 것은 아니다.

- 이상 리뷰 끝