← 블로그 목록

몬스터 설계는 타입 데이터와 개체 상태를 분리할 때 훨씬 단단해진다

RPG 몬스터 설계의 첫 질문은 ‘이 정보가 모든 고블린에게 공통인가, 이 한 마리만의 상태인가’다. 플라이웨이트 패턴처럼 타입 데이터와 개체 상태를 분리하면 메모리 중복뿐 아니라 수정 범위까지 함께 좁아지고 데이터 의미도 선명해진다. 오브젝트 풀은 멋이 아니라 생성·해제 빈도가 실제 병목일 때만 얹는 최적화라는 점도 함께 정리한다.

몬스터 설계는 타입 데이터와 개체 상태를 분리할 때 훨씬 단단해진다

몬스터 설계는 타입 데이터와 개체 상태를 분리할 때 훨씬 단단해진다

RPG나 액션 게임에서 몬스터를 설계할 때 처음에는 모든 정보를 한 객체에 다 넣고 싶어진다. 이름, 공격력, 최대 체력, 위치, 현재 체력, 상태 이상, 드롭 테이블까지 한데 모아 두는 식이다. 처음에는 편해 보이지만 몬스터 수가 늘어나면 중복과 관리 비용이 금방 커진다.

이럴 때 가장 먼저 떠올려야 하는 질문은 “이 정보가 모든 고블린에게 공통인가, 아니면 이 고블린 한 마리만의 상태인가”다. 이 구분이 선명해지면 설계도 훨씬 단단해진다.

공통 데이터와 개별 상태를 나누면 메모리와 책임이 함께 정리된다

로버트 나이스트롬의 Game Programming Patterns는 플라이웨이트 패턴을 설명하면서, 많은 객체가 공유하는 상태와 각 인스턴스마다 다른 상태를 분리하라고 말한다. 숲 속 나무 예제에서 메시와 텍스처 같은 공통 정보는 공유하고, 위치와 크기 같은 정보만 각 나무 인스턴스에 둔다.

몬스터 설계도 비슷하다.

이렇게 나누면 고블린 100마리가 있어도 “고블린 기본 스펙”은 한 번만 들고 있으면 된다. 개별 몬스터는 그 타입을 참조하면서 자기 상태만 바꾸면 된다.

이 방식의 장점은 메모리 절약보다 수정 범위 축소에 있다

사람들이 이런 설계를 들으면 먼저 메모리 최적화를 떠올리지만, 실제 장점은 수정 범위가 줄어드는 데도 있다.

고블린 기본 공격력을 5에서 6으로 바꿔야 할 때, 공통 타입 데이터 한 곳만 바꾸면 된다. 반대로 모든 인스턴스가 기본값을 복사해 들고 있으면, 어떤 값이 원본이고 어떤 값이 변형된 값인지 점점 헷갈리기 쉽다.

즉 타입/인스턴스 분리는 성능 문제이면서 동시에 설계 책임 문제이기도 하다.

그렇다고 모든 것을 공유 객체로 빼면 오히려 불편해질 수 있다

플라이웨이트는 효율적인 패턴이지만, 무조건적으로 모든 값을 공유 객체로 빼는 것이 답은 아니다. 나이스트롬도 공통 상태를 공유하는 대신 포인터 추적과 캐시 미스 같은 비용을 고려해야 한다고 설명한다.

게임 몬스터로 치면 이런 식이다.

즉 핵심은 “어디까지 공유할 것인가”를 신중하게 정하는 것이다.

오브젝트 풀은 자주 생성하고 자주 버리는 경우에만 쓰는 편이 낫다

몬스터 설계를 이야기하다 보면 오브젝트 풀도 함께 나온다. Game Programming Patterns의 오브젝트 풀 장은, 비슷한 객체를 자주 만들고 자주 없애야 할 때 고정된 풀을 두고 재사용하면 성능과 메모리 단편화 문제를 줄일 수 있다고 설명한다.

이 패턴은 탄환, 파티클, 짧게 살아 있는 이펙트에 특히 잘 맞는다. 몬스터에도 쓸 수는 있지만 모든 경우에 필요한 것은 아니다.

즉 오브젝트 풀은 “멋있어 보여서” 넣는 최적화가 아니라, 생성/해제 빈도가 실제 병목일 때 쓰는 편이 맞다.

핵심 정리

게임 몬스터 설계에서 가장 먼저 해야 할 일은 공통 타입 데이터와 개체별 상태를 분리하는 것이다. 그렇게 해야 메모리 중복이 줄고, 데이터 의미가 선명해지고, 기본 스펙 수정도 쉬워진다.

여기에 오브젝트 풀은 필요할 때만 얹는 최적화다. 즉 좋은 몬스터 설계의 출발점은 모든 것을 객체 하나에 넣는 것이 아니라, 무엇이 공유 상태이고 무엇이 현재 상태인지를 구분하는 데 있다.

참고 자료

← 목록으로
Related

함께 읽으면 좋은 글

게임 개발그래픽스컬링
컬링은 안 보이는 것을 덜 그려서 3D 장면을 버티게 만드는 기본 최적화다

3D 장면이 무거울 때는 폴리곤 수를 줄이는 것 못지않게 보이지 않는 것을 일찍 걸러내는 일이 중요하다. 백페이스, 프러스텀, 오클루전 컬링은 비슷해 보여도 해결하는 문제가 서로 다르고 비용 구조도 다르다. 안 보이는 이유가 방향 때문인지, 시야 밖이기 때문인지, 가려졌기 때문인지 구분해서 적용해야 한다는 점을 OpenGL과 Unity 문서를 함께 정리한다.

게임 개발소프트웨어 디자인아키텍처
데이터 주도 설계의 핵심은 데이터를 많이 두는 것이 아니라 경계를 잘 나누는 것이다

데이터 주도 설계는 모든 값을 JSON이나 테이블로 빼는 일이 아니다. 저장 형식과 도메인 모델 사이에 변환 계층을 두고, 자주 바뀌는 값과 시스템 개념을 구분하며, 데이터 변경이 핵심 로직까지 무차별적으로 퍼지지 않게 경계를 설계하는 일에 가깝다. 결국 중요한 것은 데이터의 양이 아니라 경계의 질이다.

소프트웨어 공학시스템 설계프로젝트 관리
대규모 소프트웨어 개발은 코드 양보다 조정 비용과 구조 설계가 더 어렵다

큰 시스템이 어려운 이유는 코드 양 그 자체보다 모듈 사이의 관계 수와 사람 사이의 조정 비용, 그리고 보이지 않는 복잡성에 있다. 프레드 브룩스의 통찰처럼 인원을 더 넣는다고 일정이 줄지 않고, 문서와 경계가 없으면 시스템은 금세 개인 의존형이 된다. 대규모 개발의 진짜 실력이 기능 구현보다 운영 현실을 견디는 구조를 만드는 데서 드러난다는 점을 정리한다.