관찰자 패턴은 가장 널리 사용되고 잘 알려져 있는 패턴이다. 게임 개발자한테는 조금 생소할수 있다.

업적 달성

업적시스템을 추가한다고 보자. ‘원숭이 100마리 잡기’ , ‘다리에서 떨어지기’, ‘목검만으로 레벨 100 달성하기’ 등등 달성할 수 있는 업적이 수백개가 존재한다고 생각해보자.

업적 종류가 많아지면 업적 코드가 컨텐츠, 시스템 코드안에 파고 들것이다. 암세포처럼 다리에서 떨어지기 같은 경우에는 충돌체크 알고리즘중에 확인해야 할것이다.

이렇게 생각을 하면 업적 코드들은 한군데 모여있기 보다 여러 코드들 사이에 떨어져서 존재하게 될것이고 이것은 코드를 이해하기 어렵고 복잡하게 만들며 구조를 다른사람이 파악하기도 어려울 것이다.

그래서 특정 기능을 담당하는 코드는 한데 모아두는게 좋다. 문제는 업적은 여러 게임 플레이 환경요소에서 발생해야 한다는 것이다. 이런 코드 전부와 커플링(연결) 되지 안고도 업적코드가 한데모여서 동작하게 하려면 어떻게 해야할 것인가?

예를 들어서 평면에 물체가 놓여 있다고 생각해보자. 바닥으로 추락하는지 추적중인 물리 엔진 코드가 있다고 생각해보자. ‘다리에서 떨어지기’ 업적을 구현하기 위해 업적 코드를 물리 코드에 곧바로 넣어서 구현하면 매우 편리하다. 하지만 이러면 코드가 지저분해지니 다음과 같이 해보자

void Physics::updateEntity(Entity& entity)
{
  bool wasOnSurface = entity.isOnSurface();
  entity.accelerate(GRAVITY);
  entity.update();

  if (wasOnSurface && !entity.isOnSurface())
  {
    notify(entity, EVENT_START_FALL);
  }
}

이 코드는 ‘이게 방금 덜어지기 시작했으니 누군지는 몰라도 알아서 하시오’ 알리기만 하는게 전부다.

업적 시스템은 물리엔진이 알림을 보낼때마다 받을 수 있도록 스스로 등록한다. 업적 시스템은 떨어지는 물체가 불쌍한 우리의 캐릭터가 맞는지, 그리고 떨어지기 전에 다리위에 있었는지를 확인한 뒤에 축포와 함께 업적을 잠금해제 시켜주면 된다.

이렇게 물리엔진 코드는 건들이지 않으면서 업적 목록을 바꾸거나 아예 업적 시스템을 떄어낼수도 있다. 물리엔진에서의 코드는 누가 받든 말든 계속 알림을 보내버린다.

작동원리

관찰자패턴을 구현해본적이 없어도 방금 설명했던 부분으로 어느정도는 감을 잡았을 것이다.