디자인 패턴/게임 프로그래밍 패턴 20

[게임 프로그래밍 패턴][20]공간 분할

개요공간 분할은 위치를 가진 객체를 위치에 따라 자료구조에 정렬하여 사용하는 패턴이다. 충돌이나 공격같이 서로 가까운 객체들을 찾아 처리해야 할 때나 특정 위치나 근처의 객체를 빠르게 찾아야 할때 성능을 개선할 수 있다.가장 간단한 방식은 고정 크기로 나눈 그리드 셀들에 해당 셀의 영역에 있는 객체를 링크드 리스트로 저장해두는 방법이다. 서로 특정 거리보다 인접한 객체들끼리 처리하고자 한다면 그 거리를 포함하는 인접 셀에 있는 개체들끼리만 거리 검사를 하여 처리하는 식으로 사용하면 된다. 각 셀들에 어떤 객체가 들어있는지가 항상 관리되어야하기 때문에 객체 생성시나 이동시 특정 셀에 넣거나 옮기는 처리가 필요하다.  인접 셀 처리포지션이 완전히 같은 객체들에 대해 처리한다고 하면 같은 셀에 있는 객체들끼리..

[게임 프로그래밍 패턴][19]객체 풀

개요객체 풀은 반복적으로 생성 및 제거되는 오브젝트를 매번 새로 만드는 것이 아닌 일정량을 미리 생성해두고 사용 중인지 아닌지 구분하여 생성시 사용중이 아닌 오브젝트를 사용하고 제거시 해당 오브젝트를 비사용으로 돌려 사용하는 패턴이다. 메모리 할당 및 해제의 오버헤드와 메모리 단편화를 막을 수 있어 메모리 성능을 향상시킬 수 있는 패턴이다. 특히 모바일같이 메모리 관리자나 GC, 관련 하드웨어들이 약한 환경에서는 메모리 단편화가 치명적이기에 더욱 유용하다. 객체 풀을 구현하는 간단한 방법은 객체 풀 클래스에서 객체들의 배열을 관리하고 각 객체에서 자신의 사용 여부를 관리한다. 객체 생성시 사용중이지 않은 객체를 사용중으로 바꾸고 초기화한 뒤 리턴하거나 자신이 관리한다. 객체 풀은 생성한 오브젝트를 리턴하..

[게임 프로그래밍 패턴][18]더티 플래그

개요더티 플래그는 계속 변경되는 기본 값을 통해 파생 값을 만들어야 할때 사용할 수 있는 패턴이다. 이는 계산과 동기화 두가지 경우가 있다. 계산은 지역 변환 행렬을 통해 월드 변환 행렬을 구하는 경우등이 있고 동기화는 로컬의 상태를 서버에 갱신하는 경우등이 있다. 더티 플래그는 파생 값이 기본 값에 동기화되어 있는지를 나타내는 플래그로 기본 값이 수정되면 true가 되고 파생 값을 갱신하면 false가 된다. 이를 통해 현재 파생 값을 그냥 쓰면 될지 기본값을 통해 갱신해야 할지 알 수 있다. 사용 예시계산에 사용하는 경우는 위에서 말한 지역 변환 행렬과 월드 변환 행렬이 있다. 업데이트에서 transform 계층 구조를 가진 오브젝트들의 지역 변환 행렬을 갱신한다고 하자. 이때 갱신된 오브젝트의 더티..

[게임 프로그래밍 패턴][17]데이터 지역성

개요데이터 지역성은 캐쉬 효율을 극대화 하기위한 패턴이다. 메모리는 접근 속도가 느리기에 한 데이터에 접근시 그 데이터와 인접한 데이터 블럭을 캐쉬로 가져와 저장해둔다. 캐쉬에 저장된 데이터에 접근하면 속도가 훨씬 빠르다. 성능이 중요한 부분은 데이터 지역성을 신경쓰면 좋다. 사용 예시연속 배열만약 각 객체별로 여러 컴포넌트를 가리키는 포인터가 있고 그러한 객체들의 포인터를 가진 전역 객체 포인터 배열이 있다고하자. 그리고 각 데이터들은 힙에 랜덤하게 할당되어있다고 하자. 그리고 게임 루프는 각 객체의 AI 컴포넌트들을 순회하며 업데이트하고, 그 다음 물리 컴포넌트들을 순회하고...하는 식으로 컴포넌트들끼리 묶어 처리한다고 하자. 이렇게 되면 캐쉬 효율이 매우 낮다. ai 업데이트들을 처리할때 한 ai ..

[게임 프로그래밍 패턴][16]서비스 중개자

개요서비스 중개자는 서비스 제공자 인터페이스를 상속한 구체 서비스 제공자를 인터페이스로 보관하는 서비스 중개자를 하나 두고 중개자를 통해 서비스를 제공하는 패턴이다. 싱글턴 패턴과 유사한데 클래스에서 자기 자신의 인스턴스를 관리하는 것이 아닌 중개자라는 다른 클래스에서 해당 서비스 제공자의 인터페이스 포인터에 서비스 제공자를 저장해둔다는 점이 다르다. 특징싱글톤과 비교되는 서비스 중개자의 특징은 서비스 제공자 객체가 바뀔수 있다는 점이다. 싱글턴은 보통 초기화 이후 이를 계속 유지하지만 서비스 중개자는 컴파일, 런타임 시점등에서 갈아 끼울 수 있다. 이를 이용하여 곳곳에서 사용하는 서비스를 한번에 수정할 수 있다. 예를 들면 오디오 서비스에서 실제 오디오 출력 서비스를 로그 출력으로 수정하는 식으로 바꿀..

[게임 프로그래밍 패턴][15]이벤트 큐

개요이벤트 큐는 한 개체의 다른 개체에 대한 특정 요청을 즉시 처리하는 것이 아닌 큐에 저장해두었다가 나중에 처리하는 것을 말한다. 크게 이벤트를 보내는 경우와 메세지를 보내는 경우가 있는데 이벤트는 큐에 특정 사건 발생시 이벤트를 넣고 등록된 리스너들에게 이를 전달하는 것이다. 이는 함수 호출등으로 구현된다. 메세지는 특정 기능을 요청하는 메세지를 큐에 넣으면 리스너가 그 내용들을 원할때 큐에서 꺼내 처리하는 것이다. 오디오 기능을 메세지를 통해 제공할 수 있다.n대m이벤트 큐는 큐에 요청을 넣는 개체 n개와 그 요청을 처리하는 개체 m개로 n대m으로 표현할 수 있다. 일대다, 다대일, 다대다 등이 많이 쓰이며 일대일은 이벤트큐보다는 그냥 큐 자료구조를 사용하는게 낫다. 특징이벤트 큐로 얻을 수 있는 ..

[게임 프로그래밍 패턴][14]컴포넌트 패턴

개요컴포넌트 패턴은 한 개체의 기능을 한 클래스에 몰아 넣는것이 아닌 여러 컴포넌트 클래스로 나누어 구현하는것을 말한다.개체 클래스는 여러 컴포넌트를 소지하게 된다. 각 컴포넌트는 메소드와 데이터를 가져 동작과 상태를 모두 나누어 가지게 된다. 특정 기능을 컴포넌트로 분리하여 구현하면 개체에 몰려있던 커플링을 분리할 수 있고 한 클래스에 코드가 몰리는것도 막을 수 있다. 또한 독립적으로 작동하는 컴포넌트라면 일반화하여 다른곳에 재활용 할 수도 있다. 언리얼 엔진의 컴포넌트나 유니티의 컴포넌트도 비슷한 개념인 것 같다.  컴포넌트간 상호작용각 컴포넌트가 완전히 독립적으로 동작하면 좋겠지만 서로 통신이 필요할 수도 있다. 이때 다음 세가지 방식으로 구현할 수 있다. 개체의 멤버 데이터를 통해 통신개체가 가진..

[게임 프로그래밍 패턴][13]타입 객체

개요타입 객체는 타입 사용 객체가 타입 객체 인스턴스를 가짐으로써 한 타입을 나타내는 패턴이다. 즉 각 인스턴스가 하나의 타입을 의미하는 타입 클래스가 있으며 해당 타입 클래스의 인스턴스를 하나 가져 해당 타입의 인스턴스를 나타내는 타입 사용 클래스가 존재한다. 이를 통해 추가적인 상속이나 클래스없이 인스턴스만으로 새로운 타입들을 만들어 나갈 수 있다.타입 객체의 인스턴스가 가진 데이터로 한 타입을 나타내는 패턴이기에 만들고자하는 타입들이 데이터로 구분될때 유용하다. 물론 타입 사용 클래스등에서 미리 구현된 기능들을 타입 객체의 데이터를 통해 적절히 조합하여 사용하는 방식으로 타입 객체에서 동작도 정의할 수 있다. 앞서 배웠던 바이트 코드 등이 하나의 예시가 될 수 있다.타입 객체 패턴은 만들고자 하는 ..

[게임 프로그래밍 패턴][12]하위 클래스 샌드박스

개요하위 클래스 샌드박스는 상위 클래스가 외부와의 커플링 및 기능 구현을 주로 담당하고 하위 클래스에서는 상위 클래스에서 제공해주는 기능들로 가상 메소드를 구현하는 구조를 이야기한다. 이는 한 상위 클래스 아래에 만들어질 여러 하위 클래스들의 커플링을 한곳으로 모으는 것과 중복되는 코드를 상위 클래스에 모아 재활용할 수 있도록 하기위해 사용된다. 스킬 클래스들을 만든다 할 때 오디오, 파티클, 플레이어 이동등의 기능 및 외부 커플링을 상위 클래스에서 메서드로 모두 구현하고 하위 스킬 클래스에서는 이들을 이용하여 스킬 사용을 나타내는 가상 메서드를 구현하는 구조가 예시이다.  상위 클래스 기능 제공 정도위에서 말한 여러 이점때문에 상위 클래스에서 기능 제공을 맡는다. 하지만 상위 클래스에 너무 많은 코드와..

[게임 프로그래밍 패턴][11]바이트 코드

개요바이트 코드 패턴은 특정 행동을 바이트 명령어로 정의하여 사용하는 패턴이다. 마법 시스템을 정의한다고 할 때 targetHP수정, TargetPosition 수정 등의 명령어들을 정의해두고 일련의 바이트 코드 하나를 마법으로 사용하는 식이다. 여기서 더 나아가 스택 머신과 그에 따른 명령어들을 추가하여 프로그래밍 언어처럼 각종 값 저장과 연산들을 사용할 수도 있다. 일련의 명령어는 한 명령어를 한 바이트로 표현하여 바이트 배열로 표현 할 수 있다. 즉 한 바이트 배열이 하나의 마법처럼 사용 될 수 있다. 또한 스택에 데이터를 삽입하는 리터럴 명령어 뒤의 바이트는 명령어가 아닌 삽입할 숫자 리터럴을 나타낸다.이렇게 바이트 배열로 마법을 정의하는 시스템을 만들었으면 기획자나 담당자가 스킬을 만들어낼 수 ..