이 흐름도는 이러한 코어 게임플레이 클래스끼리의 상관 관계를 나타냅니다. 게임은 GameMode 와 GameState 로 이루어집니다.
게임에 참여하는 사람 플레이어는 PlayerController 에 연관됩니다. 이러한 PlayerController 는 플레이어가 레벨 내 물리적 존재를 가질 수 있도록 Pawn 에 빙의됩니다. PlayerController 는 플레이어에게 입력 컨트롤, 헤드업 디스플레이 (HUD), 카메라 시야 처리를 위한 PlayerCameraManager 등을 줄 수 있습니다.
게임 프레임워크의 바탕은GameMode입니다. GameMode에서는 게임의 규칙을 설정, 예제에선 결승선을 먼저 통과하는 플레이어가 이기는 규칙입니다. 플레이어 스폰 처리도 여기서 합니다.
플레이어 셋업이 이루어지는 곳은PlayerController로, 이것이Pawn을 빙의(possess)합니다. Pawn은 게임 내 플레이어의 물리적 표현인 반면,Controller는Pawn에 빙의되어 그 동작에 대한 규칙을 설정할 수 있습니다. 우리 예제에서는Pawn이 둘 있는데, 하나는 달팽이이고 하나는 토끼입니다. 토끼는 사실상Character가 되는데, 이는Pawn의 특수한 서브클래스로 달리기나 점프같은 이동 함수성이 내장되어 있습니다. 반면 달팽이는 이동 방식이 다르기 때문에Pawn클래스를 직접 확장하면 됩니다.
Pawn자체에 이동이나 기타 게임 로직용 규칙을 포함시킬 수는 있지만, 그러한 함수성은Controller에 포함시킬 수도 있습니다.Controller는 사람 플레이어의 입력을 받는PlayerController아니면 컴퓨터의 자동 제어를 받는AIController가 될 수도 있습니다. 이 예제에서 플레이어는 달팽이를 제어할 것이기에, 달팽이Pawn은PlayerController에 빙의됩니다. 토끼는 AI 의 제어를 받는데, 언제 멈추고 달리고 낮잠을 잘 것인지 하는 규칙은 모두AIController에 설정되어 있으며, 이 컨트롤러가 토끼Character에 빙의됩니다.Camera에 제공되는 시야는 사람 플레이어에게만 의미가 있으므로, 달팽이 Pawn 에 있는 CameraComponent 하나만 PlayerCamera 에 사용될 것입니다.
게임플레이 도중 플레이어에게 받은Input으로 맵 위의 달팽이를 이리저리 움직이면서,Camera로 제공된 뷰 위에 겹쳐놓인HUD에 누가 처음으로 들어왔는지, 경과된 경주 시간은 얼마나 되는지가 표시됩니다.
월드에 플레이어, 아군, 적군 표시
Pawn
폰이란 월드의 대리인 역할을 하는 Actor 입니다. Pawn 은 Controller 에 의해 possess(빙의) 가능하며, 입력을 쉽게 받을 수 있도록 구성 가능하고, 여러가지 다양한 플레이어같은 동작을 할 수 있습니다. 참고로 Pawn 은 인간형이라 가정되지 않습니다.
Character
캐릭터는 인간형 Pawn 입니다. 기본적으로 콜리전에 쓸 CapsuleComponent 와 CharacterMovementComponent 가 들어있습니다. 기본적인 인간형 동작을 할 수 있으며, 네트워크를 통해 부드러운 이동 리플리케이션이 가능하고, 애니메이션 관련 함수성도 약간 있습니다.
플레이어 인풋 또는 AI 로직으로 폰 제어하기
Controller
컨트롤러는 Pawn 에 대한 지시를 담당하는 Actor 입니다. 보통 두 가지 형태로 등장하는데, AIController 와 PlayerController 입니다. 컨트롤러는 Pawn 에 "possess"(빙의)되어 그 폰을 제어할 수 있습니다.
PlayerController
플레이어 컨트롤러는 Pawn 과 그것을 제어하는 사람 플레이어를 잇는 인터페이스입니다. PlayerController 는 본질적으로 사람 플레이어의 의지를 나타냅니다.
AIController
AIController 는 말 그대로 Pawn 을 제어하는 의지를 시뮬레이션으로 재현한 것입니다.
플레이어에게 정보 표시하기
HUD
HUD는 "Heads-Up Display" 의 준말이며, 여러 게임에서 볼 수 있는 머리 위에 뜨는 화면 표시기같은 것으로, 생명력, 탄환 수, 총 조준선 등이 표시됩니다. 각 PlayerController 에는 보통 이와 같은 것이 하나씩 있습니다.
Camera
PlayerCameraManager 는 플레이어의 "눈"을 나타내며, 그 동작을 관리합니다. 각 PlayerController 에는 보통 하나씩 있습니다. 자세한 것은카메라문서를 참고하세요.
게임의 규칙 설정 및 기록하기
GameMode
"게임" 이라는 것의 개념은 두 개의 클래스로 나뉩니다.게임 모드와 게임 스테이트는 게임의 규칙이나 승리 조건같은 것이 포함된 게임의 정의로, 서버에만 존재합니다. 보통은 플레이 도중 바뀌는 데이터는 많이 없어야 하며, 클라이언트에서 알아야 하는 트랜션트(휘발성) 데이터는 반드시 없어야 할 것입니다.
GameState
GameState에는 접속된 플레이어 목록, 점수, 체크 게임에서 말들의 위치, 오픈 월드 게임에서 완료한 퀘스트 목록 등과 같은 것이 포함될 수 있는 게임 상태가 포함됩니다. GameState 는 서버와 모든 클라이언트에 존재하며, 최신 상태 유지를 위해 자유롭게 리플리케이트 가능합니다.
PlayerState
인간 플레이어 또는 플레이어인 척 하는 봇과 같은 게임 참여자의 상태를 말합니다. 게임의 일부로써 존재하는 플레이어가 아닌 AI 에는 PlayerState 가 없습니다. PlayerState 에 적합한 예제 데이터라면, 플레이어 이름, 점수, MOBA 게임류에서의 대전상대 레벨, CTF 게임에서 플레이어가 현재 깃발을 운반중인지 여부 등입니다. 모든 플레이어에 대한 PlayerState 는 (PlayerController 와는 달리) 모든 머신에 존재하며, 동기화 상태 유지를 위해 자유로이 리플리케이트 가능합니다.
엔진 시작 및 게임 실행 프로세스에 대한 설명 문서입니다. 여기서 보여드리는 방법은 크게 두 가지, 에디터 방법과 독립형 방법입니다
일반적인 이벤트 순서는, 엔진을 초기화시키고,GameInstance를 생성 및 초기화한 뒤, 레벨을 로드하고, 마지막으로 플레이를 시작합니다.
하지만 독립형 모드와 에디터 모드 사이의 차이점이 있는데, 일부 함수가 호출되는 정확한 순서와, 어떤 함수가 호출되는지가 다릅니다. 아래 플로우 차트는 두 방법으로 병렬 실행했을 때 게임 시작 전 수렴할 때까지의 흐름을 보여줍니다.
독립형
독립형 모드는, 에디터 외부에서 플레이하는 게임 모드로, 시작시 엔진 초기화에 이어 바로 게임 플레이에 필요한 오브젝트가 생성 및 초기화됩니다. GameInstance와 같은 오브젝트는 (Engine 생성 및 초기화와 별개로) 엔진 시작 전 생성 및 초기화되며, 엔진의 시작 함수 호출 직후 시작 맵이 로드됩니다. 공식적으로 게임플레이가 시작되는 시점은, 레벨이 적합한게임 모드와 게임 스테이트에 이어 다른액터를 생성한 이후입니다.
에디터
에디터 모드는에디터에서 플레이와에디터에서 시뮬레이트에서 사용되며, 다른 흐름으로 실행됩니다. 엔진은 에디터 실행에 필요하므로 즉시 초기화 및 시작되나,GameInstance와 같은 오브젝트의 생성 및 초기화는 사용자가 버튼을 눌러 PIE 또는 SIE 세션을 실행할 때까지 연기됩니다. 추가로 레벨의액터를 복제하여 에디터의 레벨에 영향을 끼치도록 하고,GameInstance를 포함한 모든 오브젝트는 각 PIE 인스턴스마다 별도의 사본을 갖습니다.UWorld클래스의 게임플레이 시작과 함께 에디터 방법과 독립형 방법의 재회가 이루어집니다.
* C++ 플레이어 컨트롤러의 기본 로직을 완성하면 이를 기반으로 한 블루프린트 클래스를 생성한다.
* 새롭게 생성된 블루 프린트 애셋에는 BP_TitleUIPlayerController 로 정함
* 생성된 플레이어 컨트롤러 블루 프린트를 더블 클릭한 후 오른쪽 상단의 UIWidget Class 속성을 클릭해 복사해 넣은 UI 애셋인 UI_Title을 지정한다.
.
* 컨트롤러 세팅이 끝나면, BP를 이용해 게임모드를 생성해 본다. Game Mode Base를 상속한 BP_TitleGameMode 생성
* Default Pawn Class의 정보를 아무 기능이 없는 Pawn으로 지정하고 * Player Controller class의 정보를 방금 생성한 BP_TitleGameMode로 설정한다
* 이젠 월드세팅에서 게임모드를 쉽게 변경 할 수 있다.
* UI 에서 새로시작하기 버튼을 누르면 캐릭터 선택을 위한 Select 레벨로 이동하고 * 이어하기 버튼을 누르면 GamePlay 레벨로 이동한다. 또한 Player1이라는 슬롯의 게임 데이터가 없으면, 이어하기 버튼은 누를 수 없게 비활성화 된다. * 로직은 다음과 같음
* 아직 Select 라는 레벨이 없어서 새로 시작하기 버튼을 누르면 오류가 발생한다.
* 그래서 캐릭터 선택을 담당하는 레벨인 Select 레벨을 제작해본다. * 위와 동일한 방법으로 ABUIPlayerController을 상속받은 블루프린트 BP_SelectUIPlayerController 을 생성한다 * 그리고 BP_SelectGameMode라는 게임 모드를 생성하고, PlayerController 클래스와 DefaultPawnClass를 각각 BP_SelectUIPlayerContoller와 Pawn으로 지정한다
* 이제 월드세팅에서 BP_SelectGame를 기본 게임모드로 지정하면 캐릭터 양옆으로 버튼이 보인다.
* 이제 C++로 각 버튼에 대한 로직을 구현해본다 * UserWidget을 기반으로 하는 ABCharacterSelectWidget 클래스를 생성한다 * 현재 레벨에 있는 스켈레톤 메시 액터의 목록을 가져오고, 버튼을 누를 떄마다 스켈레톤 메시 컴포넌트에 지정한 스켈레톤 메시를 변경한 ㄴ기능을 구현한다. * 현재월드에 있는 특정 타입을 상속 받은 액터의 목록은 TActorIterator<액터타입> 구문을 사용해 가져올 수 있다
1. 플레이너는 게임 진행 중에 HP를 회복할 수 없고 오직 레벨업을 할 떄만 회복된다. 2. 캐릭터는 무기를 들 떄 더 긴 공격 범위를 가진다. 3. 무기에는 공격력 증가치가 랜덤으로 부여되며, 운이 없으면 오히려 무기에 의해 공격력이 저하될 수 있다. 4. 현재 게임 스코어가 높을수록 생성되는 NPC의 레벨도 증가한다.
* 1번은 이미 구현했으므로 이번에는 2번 기능을 구현해본다.
* 무기 액터인 ABWeapon에 AttackRange라는 속성을 추가한다. * 캐릭터에 무기가 없으면 캐릭터의 AttackRange 속성을 사용하고, 캐릭터가 무기를 들면 무기의 AttackRange 속성을 사용하도록 로직을 수정한다.
* 캐릭터의 AttackRange 속성의 기본값을 80으로 낮춘다. 그리고 무기의 AttackRange 속성의 기본값을 150으로 지정하되, 해당 속성 키워드에 EditAnywgere, BlueprintReadWrite를 지정해 앞으로 ABweapon 클래스를 상속받은 무기 블루프린트에서도 공격범위 값을 다르게 설정할 수 있도록 기능을 부여한다.
* 또한 이번에는 캐릭터가 무기를 들고 있더라고 무기를 변경할 수 있도록 CanSetWeapon의 값을 무조건 true로 설정하고, 기존에 무기가 있는 경우 이를 없애고 새로운 무기를 습득하도록 로직을 변경한다.