명령 패턴이란 ?
요청 자체를 캡슐화하는 것
메서드 호출 자체를 실체화하여 객체로 감싼다는 것
좀 더 쉽게 코드와 연관지어 접근해보자면,
유저의 입력을 받아 특정 행동을 하게 하는 코드가 있다고 가정해보자.
실제 Unreal Engine에서 C++을 이용해 구현한 코드이다.
위의 handleInput() 함수는 각 프레임마다 호출될 것이고,
해당 호출 때 마다 사용자의 입력을 감지하여 Jump(), FireGun(), SwapWeapon(), LurchIneffectively() 의 함수들을 실행시킬 것이다.
Jump(), FireGun(), SwapWeapon(), LurchIneffectively() 함수들의 구현
각 행동 메서드들은 화면에 DebugMessage만 나타낼 수 있도록 간단하게 구현하였다.

단순히 작동은 하겠지만, 이런 식으로 구현하게 되면 입력 키 변경이 불가능하게 된다.
최근 거의 대부분의 게임들이 사용자가 원하는 방식으로 게임 내의 입력 키를 바꿀 수 있게 지원해주기 때문에, 이 방식은 개선이 필요하다.
즉 직접적으로 Jump()나 FireGun()을 호출하는 방법으로는 우리가 원하는 기능을 구현하기 어려울 것이다.
이 때 명령패턴이 등장하는데,
해당 함수들을 객체로 감싸 직접 함수를 호출하는 대신, 한 겹 우회할 수 있도록 구현하게 된다.
명령 패턴
이를 위해 Command 클래스와 각 행동을 실행할 수 있도록 하는 하위 클래스들을 구현해준다.
각 클래스들은 사용자의 입력을 원하는 행동에 바인딩하기 위해 execute() 함수를 오버라이딩하여 구현하였다.
주로 명령 패턴은 인터페이스에 반환 값이 없는 메서드 하나밖에 없을 확률이 높은데, 나는 Character 클래스를 수동으로 지정해주었기에 SetMyPlayerCharacter 함수 또한 구현하였다. 후에 코드 상에서 execute 할 대상을 지시할 수 있도록 구현하면 이 SetMyPlayerCharacter 함수는 불필요하게 될 것이다.
Command 클래스를 구현한 후에 PlayerController의 구조를 변환시켜준다.
각 버튼별로 Command 클래스 포인터를 지정하여 해당 버튼이 Command의 하위 클래스들 중 어떤 클래스에 바인딩할 것인지를 지정할 수 있게끔 구현한다.
각 명령들을 바인딩할 메서드들 (BindJumpMethod(), BindFireMethod(), BindSwapMethod(), BindLurchMethod()) 에서 해당 클래스로 바인딩해준다. 우선 지금은 변수로 선언해놓은 버튼들만 클래스 바인딩이 가능하지만, 이 방법을 통해 새로운 버튼들의 바인딩도 가능하게 된다.
또한 handleInput() 함수에서 기존에 각 함수들을 직접 호출하는 것 대신 각 Command 객체들의 execute()를 실행해 주어 명령 패턴을 구현할 수 있다.
그러나 이 Command 클래스에도 한계가 존재한다. 앞서 말한 것 처럼 플레이어 캐릭터를 지정해주어야 하고, 직접 해당 함수들이 플레이어 캐릭터에 접근하여 호출해야 한다.
즉, 커플링이 가정에 깔려 있다.
그래서, 이를 유연하게 만들기 위해 제어하고자 하는 객체 자체를 매개변수로 전달해주는 방법이 있다.
현재는 AMyCharacter_command 클래스에만 각 동작들의 함수가 구현되어 있기 때문에 캐스팅을 해주었는데, 동작 함수들을 다른 객체에도 구현하면 더 유연하게 구현할 수 있을 것이다.
기존에는 playerController의 handleInput 함수에서 execute 함수를 실행해주었지만,
execute의 매개변수로 어떤 액터를 넘겨주어야 할 지 명확하지 않게 되었다.
따라서 이 handleInput() 에서는 명령을 실행하는 대신, 함수 호출 시점을 지연시켜 리턴값 Command* 구현해준다.
매 프레임마다 handleInput()의 반환값에 execute를 매개변수를 넣어 실행시켜주는 코드 또한 추가해준다.
현재는 execute의 매개변수 Actor에 플레이어 캐릭터를 넣어 처음 구현과 다를 게 없지만, 명령과 액터 사이에 추상 계층을 하나 더 구현하여 액터만 바꾸어 플레이어가 게임에 존재하는 여러 액터들을 제어할 수 있도록 수정하였다.
이 방식을 통해 AI가 제어하는 캐릭터들을 제어하는 기능 또한 더 유연하게 구현할 수 있게 된다.
※ 전체 프로젝트 https://github.com/haram1117/GameDesignPatterns_Study
GitHub - haram1117/GameDesignPatterns_Study: GameDesignPatterns_Study
GameDesignPatterns_Study. Contribute to haram1117/GameDesignPatterns_Study development by creating an account on GitHub.
github.com
※ 명령 패턴 1 커밋
Command Pattern 1 · haram1117/GameDesignPatterns_Study@4d3b15b
Show file tree Hide file tree Showing 292 changed files with 675 additions and 0 deletions.
github.com
'게임 개발 > 디자인 패턴' 카테고리의 다른 글
Game Programming Design Patterns - 프로토타입 패턴 (1) (1) | 2022.08.09 |
---|---|
Game Programming Design Patterns - 관찰자 패턴 (2) (0) | 2022.08.05 |
Game Programming Design Patterns - 관찰자 패턴 (1) (0) | 2022.08.04 |
Game Programming Design Patterns - 경량 패턴 (0) | 2022.08.02 |
Game Programming Design Patterns - 명령 패턴 (2) (0) | 2022.08.02 |