unreal 8기

[7번 과제] Pawn 클래스 3D캐릭터 만들기

왕건 2026. 4. 16. 20:31

PawnClass 하나 생성

// 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"

class UCapsuleComponent;
class USkeletalMeshComponent;
class USpringArmComponent;
class UCameraComponent;

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

public:
	AMyPawn();
protected:
	virtual void BeginPlay() override;
	
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
	class UCapsuleComponent* CapsuleComp;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
	class USkeletalMeshComponent* MeshComp;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
	class USpringArmComponent* SpringArmComp;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
	class UCameraComponent* CameraComp;

public:	
	
	virtual void Tick(float DeltaTime) override;
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

};

 

헤더파일에 컴포넌트 추가

 

// 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 = false;

	CapsuleComp = CreateDefaultSubobject<UCapsuleComponent>(TEXT("CapsuleComp"));
	RootComponent = CapsuleComp;

	MeshComp = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("MeshComp"));
	MeshComp->SetupAttachment(RootComponent);

	SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArmComp"));
	SpringArmComp->SetupAttachment(RootComponent);
	SpringArmComp->TargetArmLength = 300.0f;
	SpringArmComp->bUsePawnControlRotation = true;

	CameraComp = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComp"));
	CameraComp->SetupAttachment(SpringArmComp, USpringArmComponent::SocketName);
}

 

컴포넌트 계층구조 + 상세 설정

 

Default Pawn Class 설정
Simulate Physics - False로 설정

 

 

방금 만든 Gamemode와 PawnClass를 Default로 지정


IA_Look, IA_Move 두 가지 생성

 

 

Y축이 앞으로 가는걸 기준으로 하려고 하기 때문에 
Swizzle을 통해 X에 들어오는 값을 Y의 값으로 바꿔줌 

 

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

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "MyPlayerController.generated.h"

class UInputMappingContext;
class UInputAction;
class UInputMappingContext;
class UInputAction;

UCLASS()
class PAWNCLASS_API AMyPlayerController : public APlayerController
{
	GENERATED_BODY()
	
public:
	AMyPlayerController();

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input")
	UInputMappingContext* InputMappingContext;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input")
	UInputAction* MoveAction;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input")
	UInputAction* LookAction;

protected:
	virtual void BeginPlay() override;
};

 

입력처리 함수들을 선언

 

#include "MyPlayerController.h"
#include "EnhancedInputSubsystems.h"

AMyPlayerController::AMyPlayerController()
	:InputMappingContext(nullptr),
	MoveAction(nullptr),
	LookAction(nullptr)
{
}

void AMyPlayerController::BeginPlay()
{
	Super::BeginPlay();

	if (ULocalPlayer* LocalPlayer = GetLocalPlayer())
	{
		if (UEnhancedInputLocalPlayerSubsystem* Subsystem =
			LocalPlayer->GetSubsystem<UEnhancedInputLocalPlayerSubsystem>())
		{
			if (InputMappingContext)
			{
				Subsystem->AddMappingContext(InputMappingContext, 0);
			}
	
		}
	}
}

 

게임이 시작되면 내 플레이어를 찾고,
그 플레이어의 입력 담당 시스템을 찾고,
내가 준비해둔 키 설정표(IMC)가 있으면
그걸 입력 시스템에 등록해라.

라는 의미의 코드.

 

 

만들어진 플레이어 컨트롤러에 각각 할당

 

void AMyPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	if (UEnhancedInputComponent* EnhancedInput = Cast<UEnhancedInputComponent>(PlayerInputComponent))
	{
		if (AMyPlayerController* PlayerController = Cast<AMyPlayerController>(GetController()))
		{
			if (PlayerController->MoveAction)
			{
				EnhancedInput->BindAction(
					PlayerController->MoveAction,
					ETriggerEvent::Triggered,
					this,
					&AMyPawn::Move
				);
			}

			if (PlayerController->LookAction)
			{
				EnhancedInput->BindAction(
					PlayerController->LookAction,
					ETriggerEvent::Triggered,
					this,
					&AMyPawn::Look
				);
			}
		}
	}
}

 

입력처리 함수들과 액션들을 바인딩

 

void AMyPawn::Move(const FInputActionValue& value)
{
	if (!Controller) return;

	const FVector2D MoveInput = value.Get<FVector2D>();
	const float DeltaTime = GetWorld()->GetDeltaSeconds();

	FVector DeltaLocation = FVector::ZeroVector;
	
	if (!FMath::IsNearlyZero(MoveInput.Y))
	{

		DeltaLocation += GetActorForwardVector() * MoveInput.Y * MoveSpeed * DeltaTime;
	}

	if (!FMath::IsNearlyZero(MoveInput.X))
	{
		DeltaLocation += GetActorRightVector() * MoveInput.X * MoveSpeed * DeltaTime;
	}
	
	AddActorLocalOffset(DeltaLocation, true);
}

 

Move함수를 AddActorLocalOffset()을 활용해 작성

MoveSpeed를 에티터에서 조절가능

DeltaTime을 사용하여 프레임속도와 관계없이 일정한 속도가 나도록 작성

 

void AMyPawn::Look(const FInputActionValue& value)
{
	const FVector2D LookInput = value.Get<FVector2D>();
	const float DeltaTime = GetWorld()->GetDeltaSeconds();

	const float YawValue = LookInput.X * TurnSpeed * DeltaTime;
	const float PitchValue = -LookInput.Y * LookUpSpeed * DeltaTime;
	
	AddActorLocalRotation(FRotator(PitchValue, YawValue, 0.0f));
}

 

Look함수를 AddActorLocalRotation()을 활용해 작성

Yaw와 Pitch를 계산하여 그냥 넣어주었다.

 

https://youtu.be/7NCjKlajyH8

시연 링크

'unreal 8기' 카테고리의 다른 글

2026-6-9 TIL  (0) 2026.06.09
2026-6-4 TIL  (0) 2026.06.04
[6번 과제] 회전발판과 움직이는 장애물  (0) 2026.04.09
Unreal Engine C++ 활용 프로그램 제작  (0) 2026.03.25
플랫폼 게임 구상하고 만들어보기  (0) 2026.02.26