언리얼 C++에서 Gamemode(게임 모드)는 게임의 규칙과 플레이어들의 상호작용 방식을 정의하는 클래스다. Gamemode는 게임의 전반적인 진행 방식을 결정하며, 게임의 시작과 종료, 스코어 계산, 게임 오브젝트 생성 등을 담당한다.

 

 

 


 

 

 Character & Gamemode

 

Gamemode는 C++ 클래스로 작성되며, 기본적으로 AGameModeBase 클래스를 상속하여 사용한다. Gamemode는 게임 내에서 하나의 인스턴스만 존재하며, 해당 인스턴스를 통해 게임의 전반적인 흐름을 제어한다.

Gamemode 클래스에서는 다음과 같은 기능을 구현할 수 있다.

게임 시작과 종료: Gamemode는 게임이 시작되었을 때와 종료될 때의 로직을 구현한다. 예를 들어, 게임이 시작될 때 플레이어들에게 초기화 작업을 하거나, 게임이 종료될 때 스코어를 계산하는 등의 작업을 수행한다.

게임 규칙: Gamemode는 게임의 규칙을 정의한다. 예를 들어, 게임에서 사용할 무기나 아이템의 종류, 각 플레이어의 생명력과 속도, 게임이 진행되는 지역의 크기와 형태 등을 설정할 수 있다.

플레이어 관리: Gamemode는 플레이어들의 관리를 담당한다. 예를 들어, 플레이어가 게임에 입장할 때의 초기화 작업, 플레이어가 게임에서 나갈 때의 처리, 각 플레이어의 스코어 계산 등을 수행한다.

게임 오브젝트 생성: Gamemode는 게임 오브젝트(게임 내의 모든 객체)의 생성과 소멸을 담당한다. 예를 들어, 적군을 생성하거나, 아이템이나 무기를 배치하는 등의 작업을 수행한다.

Gamemode는 게임의 규칙을 결정하고, 게임 오브젝트를 생성하며, 플레이어 관리를 담당하는 등 매우 중요한 역할을 한다. 게임 개발자는 Gamemode를 통해 게임의 전반적인 진행 방식을 구현할 수 있으며, 플레이어들이 게임을 즐길 수 있도록 만들어낼 수 있다.

 

 
01_Spawn
  C01_Properties.h .cpp
C02_Mesh
C02_Mesh_Sphere
C02_Mesh_Cone
C03_Spawner.h .cpp
02_Profiler
  C01_Log.h .cpp
C02_DrawDebug.h .cpp
Utilities
  CHelpers.h
 
CAnimInstance.h .cpp
CGameMode.h .cpp
CPlayer

 

 


 

CHelpers.h

 

CHelpers.h

더보기
#pragma once
#include "CoreMinimal.h"
class U2212_03_API CHelpers
{
public:
template<typename T>
static void CreateComponent(AActor* InActor, T** OutComponent, FName InName, USceneComponent* InParent = nullptr)
{
*OutComponent = InActor->CreateDefaultSubobject<T>(InName);
if (!!InParent)
{
(*OutComponent)->SetupAttachment(InParent);
return;
}
InActor->SetRootComponent(*OutComponent);
}
template<typename T>
static void GetAsset(T** OutObject, FString InPath)
{
ConstructorHelpers::FObjectFinder<T> asset(*InPath);
*OutObject = asset.Object;
}
template<typename T>
static void GetAssetDynamic(T** OutObject, FString InPath)
{
*OutObject = Cast<T>(StaticLoadObject(T::StaticClass(), nullptr, *InPath));
}
template<typename T>
static void GetClass(TSubclassOf<T>* OutClass, FString InPath)
{
ConstructorHelpers::FClassFinder<APawn> asset(*InPath);
*OutClass = asset.Class;
}
};

static void CreateComponent.

  • CreateComponent에 USceneComponent를 받아온다.
    • USceneComponent* InParent = nullptr 초기값 설정
    • if (!!InParent)
      • 부모가 있다면(=null이 아니라면)
    • (*OutComponent)->SetupAttachment(InParent)
      • 부모에 *OutComponent를 붙여준다.

 

static void GetClass(TSubclassOf<T>* OutClass, FString InPath)

  • F12로 들어가서 확인해보면 TSubclassOf도 템플릿으로 정의된 클래스타입이다. TClassType* Class이다. 포인터를 하나 가지고 있다. 
    • 따라서 TSubclassOf<T>* 는 2차 포인터가 된다.
  • CHelper에서 GetClass()를 만든다. 다른곳에서 Class를 생성할 때 CHelper의 GetClass()를 사용하면 좀 더 편하게 생성할 수 있다.

 

 

CPlayer 생성

 

새 C++ 클래스 - Character - CPlayer 생성

 

캐릭터인 CPlayer를 생성한 후 SpringArm, Camera, Mesh(SK_Mannequin)를 추가한다.

 

 

CPlayer.h

더보기
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "CPlayer.generated.h"
UCLASS()
class U2212_03_API ACPlayer : public ACharacter
{
GENERATED_BODY()
private:
UPROPERTY(VisibleAnywhere)
class USpringArmComponent* SpringArm;
UPROPERTY(VisibleAnywhere)
class UCameraComponent* Camera;
public:
// Sets default values for this character's properties
ACPlayer();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
private:
void OnMoveForward(float InAxisValue);
void OnMoveRight(float InAxisValue);
void OnHorizontalLook(float InAxisValue);
void OnVerticalLook(float InAxisValue);
};

키 입력

  • void OnMoveForward(float InAxisValue);
  • void OnMoveRight(float InAxisValue);
  • void OnHorizontalLook(float InAxisValue);
  • void OnVerticalLook(float InAxisValue);
  • ※코딩 컨벤션: 함수 포인터, 이벤트는 앞에 On을 붙여준다.

 

 

CPlayer.cpp

더보기
#include "CPlayer.h"
#include "Global.h"
#include "GameFramework/SpringArmComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "Components/InputComponent.h"
// Sets default values
ACPlayer::ACPlayer()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
CHelpers::CreateComponent<USpringArmComponent>(this, &SpringArm, "SpringArm", GetCapsuleComponent());
CHelpers::CreateComponent<UCameraComponent>(this, &Camera, "Camera", SpringArm);
USkeletalMesh* mesh;
//SK_Mannequin을 레퍼런스 복사하여 경로를 넣어준다.
CHelpers::GetAsset<USkeletalMesh>(&mesh, "SkeletalMesh'/Game/Character/Mesh/SK_Mannequin.SK_Mannequin'");
GetMesh()->SetSkeletalMesh(mesh);
GetMesh()->SetRelativeLocation(FVector(0, 0, -90));
GetMesh()->SetRelativeRotation(FRotator(0, -90, 0));
bUseControllerRotationYaw = false;
GetCharacterMovement()->bOrientRotationToMovement = true; //이동방향으로 회전
GetCharacterMovement()->MaxWalkSpeed = 400;
SpringArm->SetRelativeLocation(FVector(0, 0, 60));
SpringArm->TargetArmLength = 200;
SpringArm->bUsePawnControlRotation = true;
SpringArm->bEnableCameraLag = true;
}
// Called when the game starts or when spawned
void ACPlayer::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void ACPlayer::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// Called to bind functionality to input
void ACPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) //입력
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
PlayerInputComponent->BindAxis("MoveForward", this, &ACPlayer::OnMoveForward);
PlayerInputComponent->BindAxis("MoveRight", this, &ACPlayer::OnMoveRight);
PlayerInputComponent->BindAxis("HorizontalLook", this, &ACPlayer::OnHorizontalLook);
PlayerInputComponent->BindAxis("VerticalLook", this, &ACPlayer::OnVerticalLook);
}
void ACPlayer::OnMoveForward(float InAxisValue)
{
FRotator rotator = FRotator(0, GetControlRotation().Yaw, 0);
FVector direction = FQuat(rotator).GetForwardVector();
AddMovementInput(direction, InAxisValue); //이동
}
void ACPlayer::OnMoveRight(float InAxisValue)
{
FRotator rotator = FRotator(0, GetControlRotation().Yaw, 0);
FVector direction = FQuat(rotator).GetRightVector();
AddMovementInput(direction, InAxisValue); //이동
}
void ACPlayer::OnHorizontalLook(float InAxisValue)
{
AddControllerYawInput(InAxisValue);
}
void ACPlayer::OnVerticalLook(float InAxisValue)
{
AddControllerPitchInput(InAxisValue);
}

Component를 사용하기 위해 헤더를 삽입한다.

  • #include "GameFramework/SpringArmComponent.h"
  • #include "GameFramework/CharacterMovementComponent.h"
  • #include "Camera/CameraComponent.h"
  • #include "Components/CapsuleComponent.h"
  • #include "Components/InputComponent.h"

 

void ACPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)

  • PlayerInputComponent는입력을 관장한다.
  • PlayerInputComponent의 헤더는 #include "Components/InputComponent.h"
  • PlayerInputComponent.h 내부에 있는 BindAxis() 아래 참고. 

 

언리얼 내에서의 회전

  • FRotator: 0~360도
  • FRotationMatrix: 3x3 행렬
  • FQuat: 사원수Quatanium. 회전에 대한 비율을 다루기 때문에 오차가 발생하지 않는다. 짐벌락 현상만 조심하자. 
  • 언리얼에서는 1:1:1로 매칭되어 서로 바뀔 수 있다.

 

BindAxis

더보기
template<class UserClass>
FInputAxisBinding& BindAxis( const FName AxisName, UserClass* Object, typename FInputAxisHandlerSignature::TUObjectMethodDelegate< UserClass >::FMethodPtr Func )
{
FInputAxisBinding AB( AxisName );
AB.AxisDelegate.BindDelegate(Object, Func);
AxisBindings.Emplace(MoveTemp(AB));
return AxisBindings.Last();
}

 

 

 

BP_Player

CPlayer에서 설정한 값들이 적용되서 들어간다. 

 

 

 

헤더명을 모르는 경우 구글에다 검색하여 언리얼 공식문서를 참고하자.  

https://docs.unrealengine.com/4.26/en-US/API/Runtime/Engine/GameFramework/USpringArmComponent/

 


 

 

 

CGameMode

 

CGameMode.h

더보기
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "CGameMode.generated.h"
UCLASS()
class U2212_03_API ACGameMode : public AGameModeBase
{
GENERATED_BODY()
public:
ACGameMode();
};

 

 

CGameMode.cpp

더보기
#include "CGameMode.h"
#include "Global.h"
ACGameMode::ACGameMode()
{
//CHelpers를 사용하지 않는 Class 생성 방법
//ConstructorHelpers::FClassFinder<APawn> asset(L"Blueprint'/Game/BP_CPlayer.BP_CPlayer_C'");
//if (asset.Succeeded())
// DefaultPawnClass = asset.Class;
CHelpers::GetClass<APawn>(&DefaultPawnClass, "Blueprint'/Game/BP_CPlayer.BP_CPlayer_C'");
}

ClassType 경로명 작은따옴표(') 앞에 항상 _C를 붙여준다. ex. "Blueprint'/Game/BP_CPlayer.BP_CPlayer_C'"

 

 

 

 

프로젝트 세팅 - 맵&모드 - 기본 게임모드 CGameMode로 변경. 

 


 

 

 

CAnimInstance

 

새C++ 클래스 - Anim Instance - CAnimInstance 생성 

 

 

CAnimInstance.h

더보기
#pragma once
#include "CoreMinimal.h"
#include "Animation/AnimInstance.h"
#include "CAnimInstance.generated.h"
UCLASS()
class U2212_03_API UCAnimInstance : public UAnimInstance
{
GENERATED_BODY()
protected:
UPROPERTY(BlueprintReadOnly, Category = "Animation")
float Speed;
public:
//언리얼에서 오버라이딩 했으면 override 붙여준다. 의무사항
void NativeBeginPlay() override;
void NativeUpdateAnimation(float DeltaSeconds) override;
};

 

 

CAnimInstance.cpp

더보기
#include "CAnimInstance.h"
void UCAnimInstance::NativeBeginPlay()
{
}
void UCAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
{
}

 


 

 

 

실행화면

 

 

 

 

 


 

'⭐ Unreal Engine > UE FPS TPS' 카테고리의 다른 글

[UE] Collision(Overlap, hit)  (0) 2023.03.09
[UE] Character Animation, Collsion  (0) 2023.03.08
[UE] Log 출력하기, Draw Debug 구현  (0) 2023.03.03
[UE] Mesh, Log  (0) 2023.03.02
[UE] Properties  (0) 2023.02.28