플레이어 Pawn/Character 스폰
PlayerController 지정
PlayerControllerClass = ASpartaPlayerController::StaticClass();
게임 규칙 관리
GameState / PlayerState 사용
이러한 클래스들을 총괄하며 관리하는 하나의 거대한 매니저역할을 한다고 보면 된다.
언리얼 에디터 상단 메뉴에서 Tools -> New C++ Class를 클릭하고 GameMode를 검색하면 아래 사진과 같은 클래스가 나온다.
C++ 클래스를 굳이 블루프린트 클래스로 상속시켜서 하나 더 만드는 이유는 에디터에서 세부 파라미터를 수정하기 훨씬 편리하기 때문이다.
여기서 블루프린트 클래스는 C++ 클래스를 상속받는 형태로 생성되며 서로 다른 클래스라는 것을 유념해야한다. C++클래스의 확장이라고 보는 것이 좋다.
언리얼 엔진에서 GameMode를 적용하는 방법은 크게 두 가지이다.
만약 프로젝트 전역 설정과 레벨 별 설정이 충돌한다면, 레벨 별 설정이 우선 적용된다.
APawn
은 게임 세계에서 플레이어 또는 AI가 제어할 수 있는 객체를 나타낸다.
모든 플레이어나 AI 캐릭터는 기본적으로 Pawn
클래스를 기반으로 생성된다.
상대적으로 가벼운 구조로, 복잡한 이동이나 애니메이션 기능이 없다. 커스터마이징이 쉬운 구조를 원할 때 이용하는 클래스.
ACharacter
는 APawn
을 상속한 클래스이고, 인간형 캐릭터를 위해 설계된 확장된 클래스이다.
주로 행동과 애니메이션(걷기, 뛰기, 점프 등)을 지원하며, 캐릭터와 관련된 모든 기능을 제공한다.
ACharacter
는 복잡한 동작을 구현하기 위한 기능을 미리 포함한다.
UCapsuleComponent
: 충돌을 처리하기 위한 캡슐USkelealMeshComponent
: 캐릭터의 스켈레탈 메시(모델)UCharacterMovementComponent
: 이동 로직추가적으로 네트워크 복제와 AI네이게이션에 적합하도록 설계되어 있다. 인간형 캐릭터가 필요할 때 이용하는 클래스이다.
Character 기반 C++ 클래스를 생성하고 게임모드와 마찬가지로 생성한 C++클래스를 상속받는 블루프린트 클래스도 생성해준다. 이렇게 만든 BP_SpartaCharacter를 열면 왼쪽 컴포넌트 트리에 이미 여러 기본 컴포넌트가 포함되어 있는 것을 볼 수 있다.
3인칭 게임에서는 플레이어가 캐릭터의 뒤쪽이나 어깨 너머 시점을 보며 이동하는 경우가 많다. 이를 위해 2가지 컴포넌트를 추가해야한다. USpringArmComponent
와UCameraComponent
를 추가한다. 이후 GameMode 설정을 통해, 우리가 만든 캐릭터가 기본적으로 스폰되도록 구성한다.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "SpartaCharacter.generated.h"
class USpringArmComponent; // 스프링 암 관련 클래스 전방 선언
class UCameraComponent; // 카메라 관련 클래스 전방 선언
UCLASS()
class SPARTAPROJECT_API ASpartaCharacter : public ACharacter
{
GENERATED_BODY()
public:
ASpartaCharacter();
protected:
// 스프링 암 컴포넌트
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera")
USpringArmComponent* SpringArmComp;
// 카메라 컴포넌트
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera")
UCameraComponent* CameraComp;
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
};
#include "SpartaCharacter.h"
// 카메라, 스프링 암 실제 구현이 필요한 경우라서 include
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"
ASpartaCharacter::ASpartaCharacter()
{
// Tick은 일단 안 쓰므로 false
PrimaryActorTick.bCanEverTick = false;
// (1) 스프링 암 생성
SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
// 스프링 암을 루트 컴포넌트 (CapsuleComponent)에 부착
SpringArmComp->SetupAttachment(RootComponent);
// 캐릭터와 카메라 사이의 거리 기본값 300으로 설정
SpringArmComp->TargetArmLength = 300.0f
// 컨트롤러 회전에 따라 스프링 암도 회전하도록 설정
SpringArmComp->bUsePawnControlRotation = true;
// (2) 카메라 컴포넌트 생성
CameraComp = CreateDefaultSubobject<CameraComponent>(TEXT("Camera"));
// 스프링 암의 소켓 위치에 카메라를 부착
CameraComp->SetupAttachment(SpringArmComp, USpringArmComponent::SocketName);
// 카메라는 스프링 암의 회전을 따르므로 PawnControlRotation은 끔
CameraComp->bUsePawnControlRotation = false;
}
void ASpartaCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
}
USpringArmComponent::SoketName
은 FName(TEXT("Something")) 대신 사용되는 정적 멤버 변수로, USpringArmComponent 클래스에서 미리 정의된 특정 소켓 이름을 나타낸다. 하드코딩된 텍스트 대신 클래스에서 제공하는 상수값을 사용해 소켓 이름을 지정하는 더 안전하고 유지보수 가능한 방법
클래스 내부에서 static const FName SoketName;
으로 정의되어 있을 가능성이 높다.
bUsePawnControlRotation
앞의 b 접두사는 함수가 bool타입이라는 것을 명시하는 Unreal의 규칙이다. 컨트롤러가 돌아갈 때 스프링암도 같이 돌아가야하므로 true, 카메라 컴포넌트는 스프링암의 회전에 따르므로 끄도록 false
DefaultPawnClass는 "게임 시작 시 어떤 캐릭터(Pawn)를 플레이어에게 제공할 것인지"를 결정한다. 우리가 만든 SpartaCharacter가 기본 캐릭터로 스폰되도록 설정하려면 BP_SpartaGameMode에서 DefaultPawnClass를 설정해도 되지만 C++파일 SpartaGameMode에 다음과 같이 코드를 추가해도 된다.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameMode.h"
#include "SpartaGameMode.generated.h"
UCLASS()
class SPARTAPROJECT_API ASpartaGameMode : public AGameMode
{
GENERATED_BODY()
public:
ASpartaGameMode()
};
#include "SpartaGameMode.h"
#include "SpartaCharacter.h"
ASpartaGameMode::ASpartaGameMode()
{
DefaultPawnClass = ASpartaCharacter::StaticClass();
}
StaticClass()
는 언리얼 엔진의 리플렉션 시스템에 의해 모든 UObject
기반 클래스에 자동으로 생성되는 정적 메서드이다. 이 메서드는 특정 클래스의 UClass 오브젝트를 반환한다. 객체를 생성하지 않아도 클래스의 정보를 반환한다.
따라서 위의 DefaultPawnClass = ASpartaCharacter::StaticClass();
는 ASpartaCharacter 클래스의 UClass 정보를 반환하여 DefaultPawnClass 변수에 설정한다는 말이다.
DefaultPawnClass
는 AGmaeMode
클래스에 정의된 변수로, 게임에서 기본으로 사용되는 폰 클래스를 설정한다.
TSubclassOf<APawn>
이며, APawn을 상속한 클래스만 설정할 수 있다.