UE4 - C++

UE4 - 플레이어 입력 및 폰

불타는버스 2021. 7. 21. 17:21

햇갈릴 만한것 / 코드만 기재한다.

 

https://docs.unrealengine.com/4.26/ko/ProgrammingAndScripting/ProgrammingWithCPP/CPPTutorials/PlayerInput/

 

플레이어 입력 및 폰

Pawn 클래스를 확장하여 플레이어 입력에 반응시킵니다.

docs.unrealengine.com

순서대로 진행해본다.

 

1.폰 커스터마이즈

https://docs.unrealengine.com/4.26/ko/ProgrammingAndScripting/ProgrammingWithCPP/CPPTutorials/PlayerInput/1/

 

1. 폰 커스터마이즈

폰에 대한 소개입니다.

docs.unrealengine.com

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "MyPawn.generated.h"

UCLASS()
class MYSTUDY_API AMyPawn : public APawn
{
	GENERATED_BODY()

public:
	// Sets default values for this pawn's properties
	AMyPawn();

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;
	UPROPERTY(EditAnywhere)
		USceneComponent* OurVisibleComponent;
};

헤더 코드, SceneComponent*를 하나 추가한다.

 

USceneComponent는 Transform정보만을 지닌 가벼운 컴포넌트라고 한다.

동시에 어떤 컴포넌트던 대체해서 집어넣는게 가능한 듯 하다.

SceneComponent.들어갈수 있는 종류가 무수히 많다.

 


#include "MyPawn.h"
#include "Camera/CameraComponent.h"
// Sets default values
AMyPawn::AMyPawn()
{
 	// Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
	// 이 폰을 0번 플레이어가 조종하도록 설정합니다
	AutoPossessPlayer = EAutoReceiveInput::Player0;
	// 무언가를 붙일 더미 루트 컴포넌트를 만듭니다
	RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
	// 카메라와 보이는 오브젝트를 만듭니다
	UCameraComponent* OurCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("OurCamera"));
	OurVisibleComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("OurVisibleComponent"));
	// 루트 컴포넌트에 카메라와 보이는 오브젝트를 붙입니다. 카메라를 이격 및 회전시킵니다.
	OurCamera->SetupAttachment(RootComponent);
	OurCamera->SetRelativeLocation(FVector(-250.0f, 0.0f, 250.0f));
	OurCamera->SetRelativeRotation(FRotator(-45.0f, 0.0f, 0.0f));
	OurVisibleComponent->SetupAttachment(RootComponent);
}

CPP코드의 앞부분, 언리얼 4.26.2 버전에서는

카메라 컴포넌트를 쓰기위해선 #include "Camera/CameraComponent.h"로

선언 해주어야 한다.

 

언리얼에서는 필요한 객체들을 우선 더미로 생성한 후, 안에 대상을 세팅하는 식으로 진행한다.

즉 CPP코드에 생성되어있는 객체들은, New 선언만 해준 상태라고 볼 수 있다.

 

가령 StaticMesh같이 리소스가 존재하는 객체라고해도 생성과 동시에 바로 연결 시키는것은 안되고,

생성을 일단 한 후 대상 객체를 연결시키는 식으로 진행한다.

(혹은 기능이 있는데 내가 모르는것일수도 있다. 일단 현재까지 공부한 내용상 그렇다.)

 

아래는 카메라의 기본 세팅이다.

RootComponent는 액터의 Transform정도라고 생각 할 수 있다.

(SceneComponent가 Transform정도만 들고있고, RootComponent는 액터의 최상위에 배치되기 때문에)

 

2.게임입력 환경설정

https://docs.unrealengine.com/4.26/ko/ProgrammingAndScripting/ProgrammingWithCPP/CPPTutorials/PlayerInput/2/

 

2. 게임 입력 환경설정

언리얼 엔진에서 입력 환경설정 입니다.

docs.unrealengine.com

인게임에 폰이 띄웨진 모습.아직 키입력 대응은 안되어서 아무것도 할 수 없다.

https://docs.unrealengine.com/4.26/ko/ProgrammingAndScripting/ProgrammingWithCPP/CPPTutorials/PlayerInput/3/

 

3. 게임 액션 프로그래밍 및 바인딩

C++ 코드에 입력을 바인딩합니다.

docs.unrealengine.com

 FMath::Clamp는 값의 최소치와 최대치를 정해놓는 코드이다.

 

축 매핑은, 실시간으로 입력을 받으나

액션 매핑은 한번만 호출된다.

 

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "MyPawn.generated.h"

UCLASS()
class MYSTUDY_API AMyPawn : public APawn
{
	GENERATED_BODY()

public:
	// Sets default values for this pawn's properties
	AMyPawn();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	//입력 함수
	void Move_XAxis(float AxisValue);
	void Move_YAxis(float AxisValue);
	void StartGrowing();
	void StopGrowing();

	//입력 함수
	FVector CurrentVelocity;
	bool bGrowing;

	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
	UPROPERTY(EditAnywhere)
		USceneComponent* OurVisibleComponent;
};

헤더부분, 입력 대응함수와 보여주기위한 SceneComponent 세팅.(Static Mesh 용)

// Fill out your copyright notice in the Description page of Project Settings.


#include "MyPawn.h"
#include "Camera/CameraComponent.h"
// Sets default values
AMyPawn::AMyPawn()
{
 	// Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
	// 이 폰을 0번 플레이어가 조종하도록 설정합니다
	AutoPossessPlayer = EAutoReceiveInput::Player0;
	// 무언가를 붙일 더미 루트 컴포넌트를 만듭니다
	RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
	// 카메라와 보이는 오브젝트를 만듭니다
	UCameraComponent* OurCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("OurCamera"));
	OurVisibleComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("OurVisibleComponent"));
	// 루트 컴포넌트에 카메라와 보이는 오브젝트를 붙입니다. 카메라를 이격 및 회전시킵니다.
	OurCamera->SetupAttachment(RootComponent);
	OurCamera->SetRelativeLocation(FVector(-250.0f, 0.0f, 250.0f));
	OurCamera->SetRelativeRotation(FRotator(-45.0f, 0.0f, 0.0f));
	OurVisibleComponent->SetupAttachment(RootComponent);
}

// Called when the game starts or when spawned
void AMyPawn::BeginPlay()
{
	Super::BeginPlay();
	
}

// Called every frame
void AMyPawn::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	// "Grow" 액션에 따라 키우고 줄이는 것을 처리합니다
	{
		float CurrentScale = OurVisibleComponent->GetComponentScale().X;
		if (bGrowing)
		{
			// 1 초에 걸쳐 두 배 크기로 키웁니다
			CurrentScale += DeltaTime;
		}
		else
		{
			// 키운 속도대로 절반으로 줄입니다
			CurrentScale -= (DeltaTime * 0.5f);
		}
		// 시작 크기 아래로 줄이거나 두 배 이상으로 키우지 않도록 합니다.
		CurrentScale = FMath::Clamp(CurrentScale, 1.0f, 2.0f);
		OurVisibleComponent->SetWorldScale3D(FVector(CurrentScale));
	}

	// "MoveX" 와 "MoveY" 축에 따라 이동을 처리합니다
	{
		if (!CurrentVelocity.IsZero())
		{
			FVector NewLocation = GetActorLocation() + (CurrentVelocity * DeltaTime);
			SetActorLocation(NewLocation);
		}
	}
}

// Called to bind functionality to input
void AMyPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	//함수 포인터
	// "Grow" 키를 누르거나 뗄 때 반응합니다
	InputComponent->BindAction("Grow", IE_Pressed, this, &AMyPawn::StartGrowing);
	InputComponent->BindAction("Grow", IE_Released, this, &AMyPawn::StopGrowing);

	// "MoveX" 와 "MoveY" 두 이동 충의 값에 매 프레임 반응합니다
	InputComponent->BindAxis("MoveX", this, &AMyPawn::Move_XAxis);
	InputComponent->BindAxis("MoveY", this, &AMyPawn::Move_YAxis);
}

void AMyPawn::Move_XAxis(float AxisValue)
{
	// 초당 100 유닛을 앞 또는 뒤로 움직입니다
	CurrentVelocity.X = FMath::Clamp(AxisValue, -1.0f, 1.0f) * 100.0f;
}

void AMyPawn::Move_YAxis(float AxisValue)
{
	// 초당 100 유닛을 오른쪽 또는 왼쪽으로 움직입니다
	CurrentVelocity.Y = FMath::Clamp(AxisValue, -1.0f, 1.0f) * 100.0f;
}

void AMyPawn::StartGrowing()
{
	bGrowing = true;
}

void AMyPawn::StopGrowing()
{
	bGrowing = false;
}

Cpp파일. 적용시 wasd로 움직이며, 스페이스바를 누르면 점점 커지는 객체가 만들어진다.

움직이기는 한데, 충돌판정도,중력도 없어서 허공을 날아다니며 장애물을 뚫는다.

이러한 점 때문에 보통 UCharacterComponent를 상속 받아서 주인공을 만든다.