[25. The Pawn Class]
// Critter.h
public:
UPROPERTY(EditAnywhere)
UStaticMeshComponent* MeshComponent;
UPROPERTY(EditAnywhere)
class UCameraComponent* Camera;
// Critter.cpp
#include "Camera/CameraComponent.h"
ACritter::ACritter()
{
// 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;
RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComponent"));
MeshComponent->SetupAttachment(GetRootComponent());
Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
Camera->SetupAttachment(GetRootComponent());
Camera->SetRelativeLocation(FVector(-300.f, 0.f, 300.f));
Camera->SetRelativeRotation(FRotator(-45.f, 0.f, 0.f));
}
C++ 클래스로 폰을 상속받아 만든 후 블루프린트 클래스로 만들어서 월드에 배치하면 액터를 배치했던 것 처럼 따로 조작하거나 해당 폰의 카메라로 보거나 하지 않는다.
게임 모드가 지정되지 않았기 때문이다.
Critter 클래스를 블루프린트 클래스로 만들어주고(Critter_BP) 스태틱 메시를 Shape_Cone으로 설정한다.
그리고 기본적으로 생성되어있던 FirstProjectGameModeBase 클래스를 블루프린트 클래스(CritterGameMode_BP)로 만들어준다.
![](https://blog.kakaocdn.net/dn/b1CxDK/btrLjjNMEZ8/cEqqB6hWl1ypwIX1B7CLF0/img.png)
![](https://blog.kakaocdn.net/dn/z5ZYm/btrLhI150Su/HsTkewl36ZdKcSK55AkUG0/img.png)
Default Pawn Class만 Critter_BP로 바꿔주고 월드 세팅의 게임 모드를 방금 만든 CritterGameMode_BP로 변경해준다.
실행해보면 카메라가 살짝 뒤쪽에 배치되어 대각선으로 원뿔 오브젝트를 바라보게 된다.
[26. Pawn Movement Input #1]
![](https://blog.kakaocdn.net/dn/pzZVV/btrLhtqviDJ/nTzfnhH3iJNFwcAQc7u1LK/img.png)
Scale은 나중에 바인딩 될 함수에 반환되는 값이다.
프로젝트 세팅에서 바인딩을 지정해줬다면 이제 C++ 코드에서 진짜 바인딩을 해야한다.
// Critter.h
private:
void MoveForward(float Value);
void MoveRight(float Value);
// Critter.cpp
void ACritter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
// 프로젝트에 바인딩한 이름, 대상 객체, 대상 객체의 메소드 주소
PlayerInputComponent->BindAxis(TEXT("MoveForward"), this, &ACritter::MoveForward);
PlayerInputComponent->BindAxis(TEXT("MoveRight"), this, &ACritter::MoveRight);
}
여기까지는 바인딩만 한 것이라서 실행을 해도 아무런 변화가 없다.
// Critter.h
private:
void MoveForward(float Value);
void MoveRight(float Value);
FVector CurrentVelocity;
float MaxSpeed;
// Critter.cpp
ACritter::ACritter()
{
CurrentVelocity = FVector(0.f);
Maxspeed = 100.f
}
void ACritter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
FVector NewLocation = GetActorLocation() + (CurrentVelocity * DeltaTime);
SetActorLocation(NewLocation);
}
void ACritter::MoveForward(float Value)
{
// Clamp: 값이 최소, 최대값 범위를 넘으면 최소, 최대값을 반환해준다
CurrentVelocity.X = FMath::Clamp(Value, -1.f, 1.f) * MaxSpeed;
}
void ACritter::MoveRight(float Value)
{
CurrentVelocity.Y = FMath::Clamp(Value, -1.f, 1.f) * MaxSpeed;
}
이제 wasd 입력시 정상적으로 잘 움직인다.
하드 코딩이 아닌 에디터에서 편집하고 싶다면 maxSpeed를 public 영역으로 빼내고 UPROPERTY 매크로를 붙여서 에디터에서 편집할 수 있다.
[27. Pawn Movement Input #2]
시작에 앞서 Pawn을 상속받은 C++ 클래스인 Collider를 하나 만들어주자.
getter, setter 메소드는 기능이 아주 단순해서 클래스에서 정의와 선언을 한번에 해버리는 경우가 많다.
그런 경우 접두어로 FORCELINE을 붙여주면 된다. 단, 이경우 UFUNCTION과 같이 동작하지 않는다.
// Collider.h
UPROPERTY(VisibleAnywhere, Category = "Mesh")
UStaticMeshComponent* MeshComponent;
UPROPERTY(VisibleAnywhere, Category = "Mesh")
class USphereComponent* SphereComponent;
FORCEINLINE UStaticMeshComponent* GetMeshComponent() { return MeshComponent; }
FORCEINLINE void SetMeshComponent(UStaticMeshComponent* Mesh) { MeshComponent = Mesh; }
FORCEINLINE USphereComponent* GetSphereComponent() { return SphereComponent; }
FORCEINLINE void SetMeshComponent(USphereComponent* Sphere) { SphereComponent = Sphere; }
// Collider.cpp
#include "Components/SphereComponent.h"
ACollider::ACollider()
{
RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
SphereComponent = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComponent"));
SphereComponent->SetupAttachment(GetRootComponent());
SphereComponent->InitSphereRadius(40.f);
SphereComponent->SetCollisionProfileName(TEXT("Pawn"));
AutoPossessPlayer = EAutoReceiveInput::Player0;
}
구체 컴포넌트를 만들어서 루트 컴포넌트의 하위 계층에 붙인 뒤, 반지름을 정하고 콜리전 프리셋을 붙인다.
![](https://blog.kakaocdn.net/dn/rRom8/btrLiq0WPOG/yPWURG0n8NWqs6yNgBnvwk/img.png)
여기까지만 만들고 C++ 클래스를 Collider_BP 블루프린트 클래스로 만들어서 들어가보면 생각했던 구체는 아닌것이 그려져있다.
어차피 시각화를 위한 구체가 아닌 충돌을 위한 구체이므로 그려지지 않아도 상관없다.
![](https://blog.kakaocdn.net/dn/crwpMC/btrLkvUNVMw/yrz8fVTSk4m59L98Dr0Nk0/img.png)
Hidden In Game이 체크되어있으면 플레이시 보이지 않고 해제하면 보이게 된다.
Collider_BP를 월드에 배치해서 확인할 수 있다.
메시를 하드코딩해서 직접 설정할수도 있지만 일반적으로 좋은 생각은 아니다.
에디터에서 변경하는 것이 좋다.
// Collider.h
ACollider::ACollider()
{
static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshComponentAsset(TEXT("StaticMesh'/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere'"));
if (MeshComponentAsset.Succeeded())
{
MeshComponent->SetStaticMesh(MeshComponentAsset.Object);
MeshComponent->SetRalativeLocation(FVector(0.f, 0.f, -40.f));
MeshComponent->SetWorldScald3D(FVector(0.8f, 0.8f, 0.8f));
}
}
만약 하드코딩을 한다면 이렇게 할 수 있다. ConstructorHelpers라는 이름에서 보다시피 생성자에서만 할 수 있다.
[28. Pawn Movement Input #3]
Collider에 스프링 암과 카메라를 붙여보도록 하자.
// Collider.h
UPROPERTY(VisibleAnywhere, Category = "Mesh")
class UCameraComponent* Camera;
UPROPERTY(VisibleAnywhere, Category = "Mesh")
class USpringArmComponent* SpringArm;
// Collider.cpp
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"
ACollider::ACollider()
{
// .. 생략
SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
SpringArm->SetupAttachment(GetRootComponent());
SpringArm->SetRelativeRotation(FRotator(-45.f, 0.f, 0.f));
SpringArm->TargetArmLength = 400.f;
SpringArm->bEnableCameraLag = true;
SpringArm->CameraLagSpeed = 3.f;
Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
Camera->SetupAttachment(SpringArm, USpringArmComponent::SocketName);
}
getter, setter도 만들어주자.
![](https://blog.kakaocdn.net/dn/kZFLP/btrLnsXDmFr/vCZtzIntCF02TnDRkw5LeK/img.png)
컴파일 후 블루프린트 클래스에 들어오면 카메라가 스프링 암에 잘 붙어있게된다.
'언리얼 엔진 > UE4 C++' 카테고리의 다른 글
[UE C++] The Character Class #1 (0) | 2022.09.05 |
---|---|
[UE C++] The Pawn Class #2 (0) | 2022.09.05 |
[UE C++] The Actor Class #2 (0) | 2022.09.04 |
[UE C++] The Actor Class #1 (0) | 2022.09.03 |
[UE C++] Intro to Unreal Engine C++ (0) | 2022.09.03 |