언리얼 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