본문 바로가기

블루프린팅/3. 객체지향과 프레임워크

[언리얼][블루프린트]게임플레이 프레임워크 클래스 탐색

새 블루프린트를 생성하는 첫 번째 단계 중 하나는 템플릿으로 사용할 부모 클래스를 선택하는 것이다. 버튼에 표시되는 클래스를 기본 클래스라고 하며 게임 플레이 프레임워크의 일부다. 다른 클래스를 부모 클래스로 사용하려면 모든 클래스 카테고리를 확장하고 하는 클래스를 검색한다.

다음은 언리얼은 Object라는 기본 클래스의 계층을 보여준다. Pawn과 Character클래스를 자식으로 갖는 액터클래스와 Scene Component를 자식으로 갖는 Actor Component클래스와는 뿌리가 다르다는것을 알수 있다.

Pawn Class

Pawn, 폰이란 월드 내 플레이어에 대한 물리적 표현입니다.

Pawn 클래스는 플레이어나 AI 가 제어할 수 있는 모든 액터의 베이스 클래스입니다. Pawn 은 월드 내 플레이어나 AI 개체에 대한 물리적 표현입니다. 이는 플레이어나 AI 개체의 시각적인 모습 뿐만 아니라, 콜리전이나 기타 물리적 반응과 같은 측면에서 월드와의 상호작용 방식도 Pawn 이 규정한다는 뜻입니다. 특정 유형 게임에서는 게임 내에 눈에 보이는 플레이어 메시나 아바타가 없기에 헛갈릴 수가 있습니다. 그와는 무관하게 Pawn 은 여전히 게임 내 플레이어나 개체의 물리적 위치, 방향 등을 나타냅니다.

[**Character**](InteractiveExperiences/Framework\Pawn\Character) (캐릭터)는 걸어다닐 수 있는 능력을 지닌 특수 유형 Pawn 을 말합니다.
기본적으로[**Controller**](InteractiveExperiences/Framework/Controller) 와 Pawn 에는 1:1 대응 관계가 있습니다.

즉 각 컨트롤러는 어느 때고 단 하나의 폰만을 제어합니다. 마찬가지로 게임플레이 도중 스폰된 폰이 자동적으로 컨트롤러에 빙의(possess)되지는 않습니다.
블루프린트에서, 폰 파생 클래스에 동작을 추가하는 가장 좋은 방법은 SetActorLocation 입니다. 이를 통해 해당 위치로 순간이동시킬지, 아니면 sweep 시킬지를 결정할 수 있습니다. sweep 이란 폰을 해당 방향으로 이동시키다가 무언가에 걸리면 멈추게 하는 것을 말합니다.

디폴트 폰
Pawn 클래스가 월드의 플레이어나 AI 개체의 물리적 표현을 만드는 데 있어 꼭 필요한 것만 제공해 주는 반면,  DefaultPawn 서브클래스에는 추가적인 컴포넌트와 함수성이 딸려 옵니다.

DefaultPawn 클래스에는 네이티브 DefaultPawnMovementComponent, 구체형 CollisionComponent, StaticMeshComponent 가 들어 있습니다. DefaultPawnMovementComponent 와 카메라 제어는 물론 기본 이동 바인딩 추가를 위한 부울 역시 DefaultPawn 클래스에 존재하며, 기본값은 True 로 설정되어 있습니다.

DefaultPawnMovementComponent
DefaultPawnMovementComponent 에 대한 기본 이동 스타일은 무중력 비행으로 설정되어 있습니다. 보통의 MovementComponent 변수 외에 MaxSpeed, Acceleration, Deceleration 플로트 값이 포함되어 있습니다. 이 세 가지 변수는 DefaultPawn 파생 블루프린트에서도 접근 가능합니다.

관람자 폰
SpectatorPawn 클래스는 DefaultPawn 의 서브클래스입니다.
[**GameMode**](InteractiveExperiences/Framework/GameMode) 를 통해 Pawn 과 SpectatorPawn 에 대해 다양한 클래스를 기본으로 지정할 수 있으며, 이 클래스는 관람에 이상적인 단순한 프레임워크를 제공합니다. DefaultPawn 과 마찬가지로 구체형 CollisionComponent 가 있긴 하나 .DoNotCreateDefaultSubobject(Super::MeshComponentName) 구현때문에 StaticMeshComponent 는 생성되지 않습니다. SpectatorPawn 클래스에 대한 이동은 SpectatorPawnMovementComponent 에서 처리되며, 무중력 비행 동작은 DefaultPawnMovementComponent 에서와 마찬가지이고, 여기에 필요에 따라 시간 지연을 처리하거나 무시할 수 있는 코드가 추가되어 있습니다.

 

Character Class

Character Classs는 Pawn Class의 자식 클래스이므로 컨트롤러 클래스가 소유할 수 있습니다. 

캐릭터는 원래부터 약간의 기본적인 이족보행 운동 기능을 가지고 있는 Pawn의 자식클래스 입니다.
CharacterMovementComponent, CapsuleComponent,SkeletalMeshComponent 의 추가를 통해 Pawn 클래스는 고도로 특화된 Character (캐릭터) 클래스로 확장됩니다. 캐릭터는 월드에서 걷기, 달리기, 점프, 비행, 수영 등이 가능한 직립 플레이어를 표현하기 위해 디자인된 것입니다. 이 클래스에는 기본적인 네트워킹이나 인풋 모델 구현도 추가되어 있습니다.

SkeletalMeshComponent
폰과 달리 캐릭터에는 스켈레톤을 사용하는 고급 애니메이션을 위한 SkeletalMeshComponent 가 딸려옵니다. 다른 스켈레탈 메시를 Character 파생 클래스에 추가시키는 것도 가능하지만, 캐릭터에 관련된 주 스켈레탈 메시는 이것입니다. 

 

CapsuleComponent
CapsuleComponent 는 운동 콜리전에 사용됩니다. CharacterMovementComponent 에 대한 복잡한 지오메트리 계산을 위해, Character 클래스의 콜리전 컴포넌트는 직립된 캡슐 모양이라는 가정을 합니다. 콜리전 관련 자세한 내용은:

CharacterMovementComponent
CharacterMovementComponent 는 아바타가 걷기, 달리기, 점프, 낙하, 수영 등으로 이동할 때 리짓 바디 피직스를 사용하지 않도록 할 수 있습니다. 이것은 캐릭터에 국한된 것으로, 다른 클래스에서 구현할 수 없습니다. CharacterMovementComponent 에 설정할 수 있는 프로퍼티에는 낙하와 걷기의 마찰력, 공기와 물과 땅을 가로지르는 이동 속력, 부력, 중력 스케일, 캐릭터가 피직스 오브젝트에 행사할 수 있는 물리력 등에 대한 값이 포함됩니다. CharacterMovementComponent 는 애니메이션으로부터 오는 루트 모션 파라미터도 포함하며, 피직스로 사용할 수 있도록 이미 월드 스페이스에서 트랜스폼 됩니다. 자세한 것은 루트 모션 문서를 확인하시기 바랍니다.

 

Arrow 컴포넌트 : 캐릭터의 현재 방향을 나타낸다.

 

플레이어 컨트롤러 

컨트롤러 클래스에는 Player와 AI 2가지 주요 자식 클래스가 있다 .

PlayerController 는 Pawn 과 그것을 제어하는 사람 플레이어 사이의 인터페이스입니다. PlayerController 는 사실상 사람 플레이어의 의지를 나타냅니다.

Pawn및 Character 클래스는 플레이어 컨트롤러가 이벤트를 소유하고 있는 경우에만 입력 이벤트를 수신한다. 입력 이벤트는 플레이어 컨트롤러 또는 폰에 배치할 수 있다. 입력 이벤트를 플레이어 컨트롤러에 넣는 장점은 이러한 이벤트가 폰과 독립적이어서 컨트롤러 클래스가 소유하고 있는 폰 클래스를 쉽게 변경할 수 있다는 것이다.

유니티에서는 블러거가 초보라서 그런지 입력을 글로벌하게 사용하였는데 여기서는 입력이 컴포넌트의 하나라는 점이 특이하다. 실제 입력이벤트가 포함된 클래스의 인스턴스를 여러개 배치했을때 마지막 하나만 입력을 받아 좀 이상했는데 이런것 때문이었던 것 같다.

실제 이전 챕터에서 키보드F를 누르면 불이 켜지고 G를 누르면 꺼지는  블루프린트가 있었는데

그때는 Enable Input노드가 다음과 같이 연결되어서 실행시 자동으로 입력포커스를 가도록 했는데 인스턴스가 여러개일 경우 마지막 인스턴스로 포커스가 이동해서 나머지는 입력이 안되는 경우가 발생했다. 생각해보면 입력을 특정 클래스에 종속시킬게 아니라 게임메니저와 같은 싱글톤방식이 적합했다고 생각한다 하여간.

이벤트Hit노드를 추가해주므로 총으로 쏠경우 입력 컨트롤이 활성화 될수 있게 해봤다.

위와 같이 하고 컴파일후 실행해보면 인풋포커스가 잘 이동한다.

 

PlayerController 셋업시 그 안에 어떠한 함수성이, 또 Pawn 에는 어떠한 함수성이 있어야 하는지를 고려해야 합니다. 덜 복잡한 입력의 경우 Pawn 에서 모두 처리하는 것이 가능은 합니다. 하지만 게임 클라이언트 하나에 멀티 플레이어라든가, 실행시간에 동적으로 캐릭터를 바꾸는 기능같은 경우, PlayerController 에서 입력 처리를 하는 것이 나을 수도 있습니다. 이 경우 PlayerController 에서 무엇을 할 지 결정한 다음 ("웅크리기 시작", "점프" 같은) 명령을 Pawn 에 내립니다.

또한 어떤 경우에는 입력 처리나 기타 함수성을 PlayerController 에 넣는 것이 필요할 수도 있습니다. PlayerController 는 게임 내 되도록 유지되는 반면, Pawn 은 휘발성이기 때문입니다. 예를 들어 데스매치 스타일 게임플레이에서 죽고 리스폰되면서 Pawn 은 달라지더라도 PlayerController 는 똑같을 수 있습니다. 이 경우 점수를 Pawn 에 유지했다면 리셋되겠지만, PlayerController 에 유지한 경우에는 리셋되지 않을 것입니다.

 

게임모드 베이스

게임모드 베이스는 게임모드를 만들기 위한 부모 클래스다. 게임모드클래스는 게임의 규칙을 정의하는 데 사용되며, 폰, 플레이어컨트롤러, 게임 스테이트, HUD및 기타클래스를 만드는데 사용되는 기본 클래스를 지정한다. 게임모드에서 이러한 클래스를 변경하려면 다음 스크린샷과 같이 클래스 디폴트 버튼을 클릭해 디테일 패널에 표시한다.

레벨에디터에서 프로젝트의 기본 게임모드클래스를 지정하려면 편집>프로젝트 세팅을 클릭한다. 그런 다음 프로젝트 카테고리에서 맵&모드 옵션을 선택한다. 현재는 BP_FirstPersonal이 선택되어져있다.

다음 스크린샷 같이 기본 게임모드 속성의 드롭다운에서 게임모드를 선택한다.

선택된 게임모드카테고리에서 기본게임모드에서 사용되는 일부 클래스를 재정의할 수 있다.

각레벨은 서로다른 게임모드를 가질 수 있다. 레벨의 게임모드는 프로젝트의 기본게임모드보다 우선한다. 레벨에 게임모드를 지정하려면 레벨에디터에서 세팅버튼을 클릭하고 월드세팅 옵션을 선택한후 게임모드 오버라이드 속성의 드롭다운에서 GameModeBP를 선택한다.

 

게임 인스턴스

게임 인스턴스는 기본 클래스는 아니지만 게임 시작시 생성되며 게임이 종료될 때만 제거되므로 레벨 간에 게임 인스턴스 클래스와 데이터가 유지된다.

레벨이 로드될 때마다 레벨의 모든 액터및 기타 객체가 파괴되고 부활된다. 따라서 게임 인스턴스 클래스는 레벨전화에서 일부 변수값을 보존해야하는 경우에 사용할 수 있는 옵션이다.

게임에서 사용할 게임 인스턴스 클래스를 할당하려면 다음 스크린샷과 같이 레벨 에디터에서 편집>프로젝트세팅>맵&모드로 이동해서 프로젝트 세팅을 수정한다.

Pawn, 폰이란 월드 내 플레이어에 대한 물리적 표현입니다.