제대로 따라가기 (7) C++ 프로그래밍 튜토리얼 :: 일인칭 슈팅 C++ 튜토리얼 (2)


작성버전 :: 4.21.0

언리얼 엔진 튜토리얼인 일인칭 슈팅 C++ 튜토리얼에서는 C++ 코드 작업을 통해서 기본적인 일인칭 슈팅(FPS) 게임을 만드는 법을 배울 수 있다.

 

이번 튜토리얼은 각 하위 섹션들의 길이가 길어서 분할되어 작성된다.

 

튜토리얼대로 하면 문제가 발생해서 제대로 따라갈 수 없는 부분으로 동작이 가능하게 수정해야하는 부분은 빨간 블럭으로 표시되어 있다.


이번 튜토리얼에서 새로 배우게 되는 내용은 글 제일 끝에 "이번 섹션에서 배운 것"에 정리된다.

 

VisibleDefaultsOnly는 정상적으로 존재하는 UPROPERTY 지정자입니다. 제가 실수로 VisibleDefaultOnly로 오타를 내서 컴파일러가 지정자가 없다고 에러를 띄웠었습니다. 잘못된 정보로 혼동을 드린 점에 대해서 사과드립니다.

 

 

2. 캐릭터 임포트

 

이번 섹션의 목표는 일인칭 슈팅 캐릭터 구현법을 배우는 것이다.

 

 

2-1. 새 캐릭터 만들기(문서)

 

이번 단계에서는 엔진의 Character[각주:1] 베이스 클래스를 사용해서 새 캐릭터를 만들어보자. Character 클래스에는 걷기, 달리기, 점프와 같은 이족보행 동작이 기본 내장되어 있다.

 

캐릭터 클래스 추가

 

파일 드롭다운 메뉴에서 새로운 C++ 클래스... 를 선택해서 새 부모 클래스를 선택한다.

 

 

부모 클래스 선책 창이 열리면 Character 클래스를 부모로 선택하고 다음 버튼을 누른다.

 

 

새 클래스 이름을 "FPSCharacter"라 하고 클래스 생성을 클릭한다.

 

 

FPSCharacter 클래스의 생성이 완료되었다면 FPSCharacter.cpp의 BeginPlay() 함수에 FPSCharacter 클래스가 사용중인지 확인하는 다음 코드를 추가한다.

 

if (GEngine)
{
    GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, 
        TEXT("We are using FPSCharacter!"));
}

 

이전 섹션에서도 언급했듯이 전역에 선언된 GEngine 변수를 사용하기 위해서는 "Engine.h"를 포함시켜야 한다. FPSCharacter.cpp의 전처리기 리스트에 "Engine.h" 포함 선언을 추가해주자.

 

#include "Engine.h"

만약 지난 섹션에서 언급한 다른 방식인 "FPSProject.h"에 선언을 추가해두었다면 "FPSProject.h"를 포함시켜주면 된다.

 

#include "FPSProject.h"

 

코드 작성이 끝났다면 변경사항을 저장하고 에디터로 돌아가 컴파일을 진행한다.

 

C++ FPS 캐릭터 클래스를 블루프린트로 확장

 

콘텐츠 브라우저에서 생성된 FPSCharacter 클래스를 찾아서 우클릭한 뒤 FPSCharacter 기반 블루프린트 클래스 생성을 클릭한다.

 

 

BP_FPSCharacter라고 블루프린트 이름을 정하고 Blueprints 폴더를 선택한 뒤, 블루프린트 생성 버튼을 클릭한다.

 

 

기본 폰 클래스 설정

 

새로운 캐릭터 클래스를 블루프린트로 확장했으니, 이제 이 BP_FPSCharacter를 기본 폰으로 사용하도록 설정할 차례다.

 

프로젝트 세칭 창을 열고 프로젝트 섹셩에 맵 & 모드에서 Default Pawn Class 항목을 BP_FPSCharacter로 설정한다.

 

 

 

세팅이 끝났다면 프로젝트 세팅 창을 닫고 레벨 에디터에서 플레이 버튼을 클릭해서 PIE 모드로 들어가보자. 뷰포트 좌상단에 원래의 로그 메시지와 함께 새로 추가한 "We are using FPSCharacter!"라는 문구가 빨간색으로 5초간 표시될 것이다.

 

 

아직 이동에 대한 기능을 전혀 만들지 않았기 때문에 WASD를 사용해도 움직이지 않는 것이 정상적이며 FPSCharacter가 제대로 적용된 것이다.

 

다음 단계로 넘어가기 전에 Esc키를 눌러 PIE 모드에서 빠져나오자.

 

 

2-2. 축 매핑 구성(문서)

 

일반적으로 축 매핑(Axis Mappings)을 통해서 키보드, 마우스, 컨트롤러 입력을 "친근한 이름"으로 매핑시킨뒤 나중에 이동 등의 게임 동작에 바인딩할 수 있다. 축 매핑은 지속적으로 폴링되어, 부드러운 전환 및 게임 동작이 가능하다. 컨트롤러의 조이스틱 같은 하드웨어 축은 "눌렸다", "안눌렸다" 같은 식의 구분되는 입력이 아닌 연속적인 입력 수치를 제공한다. 컨트롤러 조이스틱 입력 방법이 스케일식 동작 입력을 제공해 주기는 하지만, 축 매핑으로 WASD 처럼 지속적 폴링되는 게임 동작을 위한 일반 이동 키 매핑도 가능하다.

 

프로젝트 세팅 창을 열고 엔진 섹션의 입력을 선택한다. 그리고 입력 매핑 세팅을 다음처럼 구성한다.

 

 

 

2-3. 캐릭터 동작 함수 구현(문서)

 

이번 단계에서는 Player Input Component를 구성하고, FPSCharacter 클래스에 다음 함수들을 구현한다.

 

MoveForward();

MoveRight();

 

무브먼트 함수 인터페이스

 

에디터에서 축 매핑을 구성했으니, 매핑에 바인딩할 함수들을 구현하자.

 

FPSCharacter.h에서 클래스 하단부에 다음 함수들의 선언을 추가한다.

 

UFUNCTION()
void MoveForward(float AxisValue);

UFUNCTION()
void MoveRight(float AxisValue);

 

함수 위에 붙여준 UFUNCTION() 매크로는 엔진에게 이 함수들을 인식시켜 직렬화(Serialization), 최적화, 기타 엔진 함수성에 포함될 수 있도록 해준다.

 

동작 함수 구현

 

전형적인 FPS 조작법에서, 캐릭터의 동작 축은 카메라에 상대적이다. "전방"이란 "카메라가 향하는 방향"을, "우측"이란 "카메라가 향하는 방향의 우측"을 뜻한다. 캐릭터의 제어 방향을 구하는 데는 PlayerController를 사용할 것이다. 또한 MoveForward() 함수는 제어 회전의 피치 컴포넌트를 무시하고 입력을 XY 면으로 제한시켜 위아래를 쳐다보더라도 캐릭터는 땅과 평행으로 움직일 수 있도록 한다.

 

FPSCharacter.cpp에서 AFPSCharacter::SetupPlayerInputComponent() 함수의 하단에 다음 코드를

 

InputComponent->BindAxis("MoveForward", this, &AFPSCharacter::MoveForward);
InputComponent->BindAxis("MoveRight", this, &AFPSCharacter::MoveRight);

 

그리고 MoveForward()함수와 MoveRight()함수를 구현한다.

 

void AFPSCharacter::MoveForward(float AxisValue)
{
    FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::X);
    AddMovementInput(Direction, AxisValue);
}

void AFPSCharacter::MoveRight(float AxisValue)
{
    FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::Y);
    AddMovementInput(Direction, AxisValue);
}

 

캐릭터 동작 테스트하기

 

구현이 모두 끝났다면, 변경사항들을 저장하고 에디터로 넘어가서 컴파일을 한다.

 

컴파일이 끝나면 플레이 버튼을 눌러서 PIE 모드를 실행한 뒤, WASD 키를 눌러서 캐릭터가 전후좌우로 움직이는지 확인해보자.

 

성공적으로 움직인다면 Esc를 눌러서 PIE 모드를 빠져나오고 다음 파트로 넘어간다.

 

 

 

 

 

2-4. 마우스 카메라 컨트롤 구현(문서)

 

이번 단계에서는 캐릭터의 시야 및 이동 방향을 마우스로 조정하는 기능을 추가한다.

 

마우스 축 매핑 추가

 

프로젝트 세팅 창에서 입력 매핑을 다음과 같이 추가한다.

 

 

입력 처리 구현

 

회전과 쳐다보기에 대한 마우스 입력 처리를 하는 코드를 추가할 차례이다. Character 베이스 클래스는 카메라 회전 컨트롤에 대해서 다음과 같은 필수 함수 둘을 제공한다. 그렇기 때문에 FPSCharacter 클래스에 별도의 함수를 정의하고 구현할 필요없이 바로 AFPSCharacter::SetupPlayerInputComponent() 함수에 바인딩하는 코드를 추가하면 된다.

 

InputComponent->BindAxis("Turn", this, &AFPSCharacter::AddControllerYawInput);
InputComponent->BindAxis("LookUp", this, &AFPSCharacter::AddControllerPitchInput);

 

마우스 카메라 컨트롤 테스트

 

변경 사항들을 저장하고 에디터로 넘어가서 컴파일을 진행한 뒤, 플레이 버튼을 누르고 카메라를 움직여서 카메라가 회전하는 것을 확인해보자.

 

확인을 마쳤다면 Esc를 눌러서 PIE 모드에서 빠져나온다.

 

 

2-5. 캐릭터 점프 구현(문서)

 

액션 매핑은 별도의 이벤트에 대한 입력을 다루며, "친근한 이름"에 매핑시켜 나중에 이벤트 주도형 동작에 바인딩시킬 수 있도록 해준다. 최종 효과는 키나 마우스 버튼, 혹은 키패드 버튼에 대해서 누르기/떼기를 통해서 게임 동작을 실행시키도록 하는 거이다.

 

이번 단계에서는, 스페이스 바에 대한 액션 매핑을 구성하여 캐릭터에 점프 능력을 추가하는 것이다.

 

점프 액션 매핑

 

프로젝트 세팅 창을 열고 엔진 섹션에서 입력을 선택한다. 그리고 액션 매핑을 다음과 같이 추가한다.

 

 

입력 처리 구현

 

Character 베이스 클래스의 인터페이스(*.h) 파일 안을 보면, 캐릭터 점프에 대한 지원이 내장되어 있는 것을 볼 수 있다. 캐릭터 점프는 bPressedJump 변수에 묶여 있어서, 점프 키를 누르면, 이 변수를 true로, 떼면 false로 설정해주기만 하면 된다.

 

FPSChararcter.h에 다음 두 함수의 선언을 추가한다.

 

UFUNCTION()
void StartJump();

UFUNCTION()
void StopJump();

 

그리고 FPSCharacter.cpp에 함수의 구현을 추가해준다.

 

void AFPSCharacter::StartJump()
{
    bPressedJump = true;
}

void AFPSCharacter::StopJump()
{
    bPressedJump = false;
}

 

구현이 끝났으면 SetupPlayerInputComponent() 함수에 바인딩 코드를 추가한다.

 

InputComponent->BindAction("Jump", IE_Pressed, this, &AFPSCharacter::StartJump);
InputComponent->BindAction("Jump", IE_Released, this, &AFPSCharacter::StopJump);

 

캐릭터 점프 테스트

 

변경 사항을 저장하고, 에디터로 돌아가서 컴파일 한다. 그리고 플레이 버튼을 눌러서 PIE에 들어가서 스페이스 바를 눌러서 캐릭터의 점프가 정상적으로 동작하는지 확인해보자.

 

점프가 정상적으로 동작한다면 Esc키를 눌러서 PIE 모드에서 빠져나온다.

 

 

2-6. 캐릭터에 메시 추가(문서)

 

이번 단계에서는 캐릭터에 스켈레탈 메시를 추가한다. Character 클래스는 기본적으로 우리가 쓸 SkeletalMeshComponent를 생성해 주므로, 어떤 스켈레탈 메시를 사용할지 알려주기만 하면 된다.

 

이 튜토리얼에서 사용되는 기본 스켈레탈 메시는 파트 제목 옆에 문서 링크를 통해서 들어가면 샘플 메시라는 링크에서 받을 수 있다.

 

스켈레탈 메시 임포트

 

콘텐츠 브라우저의 콘텐츠 폴더에 들어가서 파일 창에 우클릭하여 /Game에 임포트... 를 선택해서 임포트 대화창을 연다.

 

 

아까 다운받아서 압축해제한 GenericMale.fbx 메시 파일을 찾아 선택하고 열기를 클릭하여 메시를 프로젝트에 임포트 시작한다.

 

콘텐츠 브라우저에서 FBX 임포트 옵션 대화창이 뜬다. 임포트를 클릭하면 프로젝트에 메시가 추가된다.

 

저장 버튼을 클릭해서 임포트된 메시를 저장한다.

 

삼인칭 메시 구성

 

BP_FPSCharacter 아이콘을 더블클릭해서 블루프린트 에디터를 열고 컴포넌트 탭에서 Mesh 컴포넌트를 선택한다.

 

 

디테일 패널의 메시 섹션으로 스크롤해 내려가서 없음이라고 되어있는 드롭다운 메뉴를 클릭해서 GenericMale 스켈레탈 메시를 선택해서 넣는다.

 

 

Z 위치를 -88.0으로 설정해서 SkeletalMeshComponent를 CapsuleComponent에 정렬시킨다.

 

 

SkeletalMeshComponent는 다음과 같은 상태일 것이다.

 

 

 

일반적으로 CapsuleComponent안에 SkeletalMeshComponent이 포함되고, ArrowComponent와의 방향이 일치해야 캐릭터가 월드에서 정상적으로 돌아다닐 수 있다.

 

스켈레탈 메시 설정이 끝났다면 BP_FPSCharacter 블루프린트를 컴파일하고 저장한 뒤에 블루프린트 에디터를 닫자.

 

PIE 모드에서 새 메시 확인

 

레벨 에디터에서 플레이 버튼을 클릭하면 캐릭터를 따라오는 메시의 그림자가 보일 것이다.

 

 

Esc를 눌러 PIE 모드를 빠져나오자.

 

 

 

 

 

2-7. 카메라 뷰 변경(문서)

 

이전 단계에서 살펴보았을 때, 별도의 설정을 하지 않은 기본 카메라의 위치는 메시의 목 안쪽에 위치했었다. 이번 단계에서는 카메라(위치나 시야같은) 프로퍼티 조정에 사용할 수 있는 적합한 FPS 카메라를 구성해보자.

 

카메라 컴포넌트 붙이기

 

FPSCharacter.h에 다음 코드를 추가한다.

 

UPROPERTY(VisibleAnywhere)
UCameraComponent* FPSCameraComponent;

 

그리고 FPSCharacter.cpp의 AFPSCharacter::AFPSCharacter() 생성자 함수에 다음 코드를 추가해준다.

 

FPSCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
FPSCameraComponent->SetupAttachment(GetCapsuleComponent());
FPSCameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, 50.0f + BaseEyeHeight));
FPSCameraComponent->bUsePawnControlRotation = true;

 

이 코드는 카메라의 위치를 캐릭터의 눈 살짝 위쪽으로 잡으면서 폰이 카메라 로테이션을 제어할 수 있도록 해준다.

 

 

이대로 빌드하면 Camera Component에서 에러가 발생해서 컴파일에 실패할 수 있다. 코드를 작성할 때는 에러가 뜨지 않아서 방심했지만 이 에러는 충분이 아는 에러일 것이다. 지금 비주얼 스튜디오가 한글 버전이라 로그가 깨져있지만 튜토리얼을 진행하면서 생긴 경험으로 미루어 짐작하건데, 헤더의 30라인에서 발생하는 에러는 UCameraComponent가 정의되지 않았다는 에러일 것이다. UCameraComponent 선언 앞에 class를 붙여주자.

 

UPROPERTY(VisibleAnywhere)
class UCameraComponent* FPSCameraComponent;

 

새 카메라 테스트

 

변경사항을 저장하고, 에디터에서 컴파일한 후, 플레이 버튼을 눌러서 테스트 해보자.

 

 

2-8. 캐릭터에 일인칭 메시 추가(문서)

 

FPS에서 흔히 사용되는 방법은, 전신 바디 메시 하나, 무기와 손 메시하나, 이렇게 별개의 캐릭터 메시 두 개를 사용하는 것이다. 전신 메시는 삼인칭 시첨에서 캐릭터를 보거나 다른 캐릭터를 볼대 사용되고, 플레이어가 일인칭 시점에서 게임을 볼 때는 이 전신 메시를 숨긴다. 그리고 "무기와 손" 메시는 전형적으로 카메라에 붙여 플레이어가 일인칭 시점에서 맵을 볼 때 플레이어에게만 보이는 것이다. 이 파트에서는 캐릭터에 일인칭 메시를 추가해보자.

 

일인칭 캐릭터 메시 추가

 

비주얼 스튜디오로 이동해서 FPSCharacter.h를 열고 다음 코드를 추가한다.

 

UPROPERTY(VisibleDefaultsOnly, Category = "Mesh")
USkeletalMeshComponent* FPSMesh;

 

그리고 FPSCharacter.cpp의 AFPSCharacter::AFPSCharacter() 생성자 함수에 다음 코드를 추가하여 일인칭 메시를 생성하고 설정해준다.

 

FPSMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("FirstPersonMesh"));
FPSMesh->SetOnlyOwnerSee(true);
FPSMesh->SetupAttachment(FPSCameraComponent);
FPSMesh->bCastDynamicShadow = false;
FPSMesh->CastShadow = false;

 

SetOnlyOwnerSee는 이 메시가 이 Character에 빙의(Possession)한 PlayerController에게만 보인다는 의미다. 이 코드는 메시를 카메라에 붙이고 배경 그림자를 끈다. 만약 카메라에 붙은 팔의 그림자가 보이면 기괴한 모습이 될 것이다.

 

그 아래쪽에 다음 코드를 추가하여 소유 캐릭터에서 기존 삼인칭 메시를 숨긴다.

 

GetMesh()->SetOwnerNoSee(true);

 

이제 코드의 변경 사항을 저장하고 에디터로 돌아가서 컴파일을 진행한다.

 

만약 에디터 컴파일로 곧바로 변경 사항이 반영되지 않는다면 에디터를 종료하고 솔루션 탐색기에서 FPSProject를 찾아서 우클릭하고 빌드(Build)를 선택해서 프로젝트를 새로 빌드하고 다시 실행하면 변경 사항이 반영된다.

 

 

빌드 완료 후, PIE 모드에서 살펴보면 캐릭터의 메시가 더 이상 보이지 않는 것을 알 수 있다.

 

 

메시 블루프린트 빌드

 

계속하기 전에, 다음 링크에서 샘플 메시를 다운로드해서 압축을 풀어야 한다. "일인칭 스켈레탈 메시"

 

콘텐츠 브라우저의 콘텐츠 파일창에서 우클릭해서 /Game에 임포트를 선택한다.

 

 

HeroFPP.fbx 메시 파일을 찾아 임포트 한다.

 

콘텐츠 브라우저에서 Blueprints 폴더로 들어가서 BP_FPSCharacter 아이콘을 더블클릭해서 블루프린트 에디터를 연다.

 

컴포넌트 탭에서 FPSMesh 컴포넌트를 찾는다.

 

 

FPSMesh 컴포넌트는 FPSCameraComponent의 자손이라, 카메라에 항상 붙어있다.

 

컴포넌트 탭에서 FPSMesh를 클릭한다.

 

디테일 탭에서 Mesh 섹션으로 스크롤해 내려가서 "없음"이라는 드롭다운 메뉴를 클릭해서 HeroFPP 스켈레탈 메시를 선택하여 뷰포트에 팔을 추가한다.

 

 

 

새로 추가된 HeroFPP 스켈레탈 메시는 뷰포트 안에서 다음과 같이 보일 것이다.

 

 

새로 추가된 메시의 트랜스폼이 카메라 앞에 오도록 조절한다. 위치를 로, 회전을 {-180, 50, -180}으로 설정한다.

 

 

블루프린트 에디터를 닫기 전에 BP_FPSCharacter 블루프린트를 반드시 컴파일하고 저장하자.

 

게임 내 새 메시 확인

 

레벨 에디터에서 플레이 버튼을 클릭해서 게임 내에서 새 메시를 확인한다.

 

 

Esc키를 눌러서 PIE 모드에서 빠져나오자.

 

다음 섹션에서는 발사체(Projectile) 구현법을 배워보자.

 


 

이번 섹션에서 배운 것

 

1. FRotatorMatrix

 

FRotatorMatrix RotatorMatrix;

 

행렬에서 이동 행렬을 뺀 순수하게 회전에 대한 행렬이다.

 

RotatorMatrix.GetScaledAxis(EAxis::X);

 

행렬의 크기에 의해서 스케일링된 행렬의 축을 가져오는 함수

 

2. ACharacter

 

Controller;

 

캐릭터를 제어하는 컨트롤러에 대한 변수

 

Controller->GetControlRotation();

 

컨트롤 회전을 가져오는 함수. 이것은 카메라 방향(예 : 3 인칭보기)과 다를 수 있는 완전한 목표 회전이며 제어된 Pawn (시각적으로 피치를 두거나 롤하지 않도록 선택할 수 있음)의 회전과 다를 수 있다.

 

AddControllerYawInput();

 

캐릭터 클래스에서 기본적으로 지원하는 Yaw 회전 처리 함수. 이 함수를 마우스 좌우 이동 입력과 바인딩하면 카메라 좌우 회전하는 기능을 만들 수 있다.

 

AddControllerPitchInput();

 

캐릭터 클래스에서 기본적으로 지원하는 Pitch 회전 처리 함수.

 

bPressedJump = true;

 

캐릭터 클래스에서 기본적으로 지원하는 점프 처리 변수. true가 되면 캐릭터 클래스에서 자동으로 점프를 처리해준다.

 

3. UCameraComponent

 

CameraComponent->bUsePawnControlRotation = true;

 

이 카메라 컴포넌트가 폰의 컨트롤 회전을 따라서 회전할 지를 결정하는 변수

 

4. USkeletalMeshComponent

 

USkeletalMeshComponent* SkeletalMeshComponent;

 

애니메이션을 사용할 수 있는 스켈레탈 메시 애셋의 인스턴스를 만드는데 사용되는 컴포넌트.

 

SkeletalMeshComponent->SetOnlyOwnerSee(true);

 

UPrimitiveComponent 클래스에서 상속받은 함수로 이 메시를 소유한 플레이어만 이 메시를 볼 수 있게 하는 함수

 

SkeletalMeshComponent->bCastDynamicShadow = false;

 

사전에 계산되지 않은 실시간 그림자를 그려야하는지에 대한 변수. CastShadow가 true일 때만 작동한다.

 

SkeletalMeshComponent->CastShadow = false;

 

그림자를 그려야하는지에 대한 변수

 

SkeletalMeshComponent->SetOwnerNoSee(true);

 

이 메시를 소유한 플레이어에게만 보이지 않도록 하는 함수

 

  1. Pawn 클래스에서 파생되었다. [본문으로]

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

제대로 따라가기 (6) C++ 프로그래밍 튜토리얼 :: 일인칭 슈팅 C++ 튜토리얼 (1)

작성버전 :: 4.21.0

 


언리얼 엔진 튜토리얼인 일인칭 슈팅 C++ 튜토리얼에서는 C++ 코드 작업을 통해서 기본적인 일인칭 슈팅(FPS) 게임을 만드는 법을 배울 수 있다.

 

이번 튜토리얼은 각 하위 섹션들의 길이가 길어서 분할되어 작성된다.

 

튜토리얼대로 하면 문제가 발생해서 제대로 따라갈 수 없는 부분으로 동작이 가능하게 수정해야하는 부분은 빨간 블럭으로 표시되어 있다.


이번 튜토리얼에서 새로 배우게 되는 내용은 글 제일 끝에 "이번 섹션에서 배운 것"에 정리된다.

 

1. 프로젝트 구성

 

1-1. 프로젝트 구성(문서)

 

언리얼 엔진을 실행하고 프로젝트 브라우저에서 새 프로젝트 탭에서 C++탭을 선택한다.

 

기본 코드(Basic Code)를 선택하고 프로젝트 이름을 "FPSProject"[각주:1]로 입력한다. "시작용 콘텐츠 없음"으로 하여 프로젝트를 생성한다.

 

 

언리얼 에디터에서 프로젝트가 열리면, 플레이 버튼을 눌러서 에디터에서 플레이(PIE, Play In Editor) 모드로 들어가본다. WASD키를 이용해서 이동하거나 마우스를 이용해서 화면의 방향을 전환할 수 있다.

 

 

Esc키를 누르거나, 중지 버튼을 눌러서 PIE 모드를 빠져나간다.

 

 

레벨 탐험을 마쳤다면 Contents 폴더 안에 Maps 폴더를 생성한다.

 

 

파일 메뉴에서 현재 레벨을 다른 이름으로 저장... 을 선택하여 레벨을 Maps 폴더에 "FPSMap"으로 저장한다.

 

 

편집 메뉴에서 프로젝트 세팅을 클릭한다.

 

 

프로젝트 세팅 창에서 프로젝트 섹션의 맵 & 모드에 Editor Startup Map을 우리가 만든 FPSMap으로 설정해준다.

 

 

프로젝트 세팅 창을 닫고, 프로젝트를 저장한 뒤, 다음 단계로 이동하자.

 

 

1-2. Visual Studio에서 프로젝트 열기(문서)

 

Game Mode는 게임의 규칙과 승리 조건등을 정의하는 클래스로, 프로젝트를 구성할 때, 언리얼 엔진이 기본 Game Mode 클래스를 생성해주었다. 우리는 이 Game Mode에 기본 게임플레이 프레임워크 유형에 사용될 기본 클래스를, Pawn, PlayerController, HUD 등을 포함해서 설정할 계획이다. 이 파트에서는 에디터를 통해서 비주얼 스튜디오를 열고 거기서 프로젝트의 Game Mode 클래스를 확인해 볼 것이다.

 

언리얼 에디터의 파일 메뉴에서 Visual Studio 열기를 선택하여 비주얼 스튜디오를 연다.

 

 

비주얼 스튜디오가 열리면, 솔루션 탐색기를 통해서 프로젝트에 포함된 소스파일(.cpp)과 헤더파일(.h)가 보인다.

 

 

FPSProjectGameMode.cpp 안에 다음과 같은 코드가 있을 것이다.

 

#include "FPSProject.h"
#include "FPSProjectGameMode.h"

 

언리얼 엔진이 버전업 되면서 프로젝트에 자동 생성되는 Game Mode 클래스명 끝에 Base가 붙도록 변경되었다. 그래서 열어봐야할 소스파일의 이름은 "FPSProjectGameModeBase.cpp가 된다. 이것은 헤더파일에도 포함되는 것이다.

 

그리고 처음에 불필요한 빌드 및 컴파일 시간은 줄이기 위해서 기본적으로 필요한 헤더를 제외한 헤더의 포함을 최소화 하도록 변경되었기 때문에 FPSProjectGameModeBase.cpp 파일의 전처리기에 "FPSProject.h"가 포함되어 있지 않을 것이다. 그렇기 때문에 소스파일의 내용은 다음과 같을 것이다.

 

#include "FPSProjectGameModeBase.h"

 

다음 부분 부터는 FPSProjectGameModeBase를 기준으로 설명할 것이다.

 

FPSProjectGameModeBase.h 안에는 다음과 같은 코드가 있다.

 

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "FPSProjectGameModeBase.generated.h"

/**
 *
 */
UCLASS()
class FPSPROJECT_API AFPSProjectGameModeBase : public AGameModeBase
{
    GENERATED_BODY()
};

 

이제 프로젝트에 코드를 추가할 준비가 완료되었다.

 

 

 

 

 

1-3. 로그 메시징 추가(문서)

 

이 파트에서는 로그 메시지를 사용해서 언리얼 엔진에서 제공되는 기본 Game Mode가 아닌 FPSProjectGameModeBase가 실제로 사용되는지 점검해볼 것이다. 로그 메시지는 개발 도중 코드를 점검하고 디버깅하는데 쓰이는 유용한 도구이다.

 

FPSProjectGameModeBase.h의 클래스 선언 하단에 다음 함수 선언을 추가하자.

 

public:
    virtual void StartPlay() override;

 

그리고 FPSProjectGameModeBase.cpp로 가서 함수의 구현을 작성한다.

 

void AFPSProjectGameModeBase::StartPlay()
{
    Super::StartPlay();

    if (GEngine)
    {
        GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("Hello World, this is FPSGameMode!"));
    }
}

 

이 부분에서는 GEngine이 정의되지 않았다는 문제가 발생할 것이다. 이 문제는 FPSProjectGameModeBase.cpp의 전처리기 파트에 "Engine.h"를 포함시켜주면 해결된다.

 

참고로 이 Engine 헤더는 덩치가 꽤나 큰 헤더기 때문에 필요할 때마다 이곳 저곳에서 포함시켜서 사용하는 것보다는 "FPSProject.h" 같은 헤더에 미리 선언해두고 이 "FPSProject.h"를 포함시켜서 사용하는 편이 좋을 수 있다.

 

#include "Engine.h"

 

코드 작성이 모두 끝났다면 변경사항들을 저장하고 에디터로 넘어간다.

 

 

1-4. 프로젝트 컴파일(문서)

 

이 파트에서는 프로젝트를 컴파일하여 코드 변경사항을 게임에 반영시켜볼 것이다.

 

에디터로 돌아왔다면, 컴파일 버튼을 클릭해서 코드를 컴파일한다.

 

 

플레이 버튼을 눌러서 PIE모드에 들어가서 화면에 로그가 뜨는지 확인해보자.

 

 

하지만 PIE 모드에 들어가도, 화면에 로그가 나타나지 않을 것이다. 그 이유는 아직 기본 Game Mode를 사용하고 우리가 만든 FPS Game Mode를 적용하지 않았기 때문이다.

 

그럼 이제, Esc를 눌러 PIE 모드를 중지하고 다음 단계로 넘어가자.

 

CPP Game Mode 클래스를 블루프린트로 확장

 

먼저, 콘텐트 브라우저의 콘텐츠 폴더 안에 Blueprints 폴더를 만든다.

 

 

C++클래스/FPSProject 폴더 안의 FPSGameModeBase 클래스를 우클릭해서 "FPSProjectGameModeBase 기반 블루프린트 클래스 생성"을 선택한다.

 

 

새 블루프린트 클래스의 이름을 BP_FPSProjectGameModeBase로 짓고, Blueprints 폴더를 선택한 뒤, 블루프린트 클래스 생성 버튼을 누른다.

 

 

새로 생성한 블루프린트 클래스가 Blueprints 폴더에 생긴 것을 볼 수 있다. 블루프린트를 저장하고 블루프린트 에디터를 닫자.

 

 

 

1-5. 디폴트 게임 모드 설정(문서)

 

새로 만든 게임 모드를 블루프린트로 확장시키는데 성공했으니, 이번 파트에서는 프로젝트가 FPSProjectGameModeBase를 기본 게임 모드로 사용하도록 설정해줘야 한다.

 

편집 메뉴에서 프로젝트 세팅창을 연다.

 

프로젝트 세팅 창이 열리면 프로젝트 섹션 아래의 맵 & 모드를 선택하고 Default GameMode 드롭다운에서 BP_FPSProjectGameModeBase를 선택한다.

 

 

프로젝트 세팅 메뉴를 닫고 레벨 에디터의 플레이 버튼을 클릭하면 뷰포트 좌상단 구성에서 "Hello World, this is FPSGameMode!" 라는 문구가 5초간 노란색으로 표시되는 것을 볼 수 있다.

 

 

 

 

이제 프로젝트 구성이 끝났다. 다음 섹션에서부터는 캐릭터를 구현하는 방법을 배우게 될 것이다.

 

 

 

 

 

 


 

이번 섹션에서 배운 것

 

1. AGameMode

 

StartPlay();

 

플레이가 시작되었을 때, 게임 모드에서 액터들의 BeginPlay() 함수를 호출하는 역할.

 

2. GEngine

 

GEngine;

 

전역에 선언되어 있는 엔진 포인터. 사용하기 위해서는 "Engine.h"를 포함해줘야 한다. 엔진에서 실행되는 경우가 아닐 경우, 값이 유효하지 않을 수 있으니 사용하기 전에 반드시 GEngine이 유효한 상태인지 체크하고 사용해야한다.

 

GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("Hello World, this is FPSGameMode!"));

 

뷰포트에 디버그 메시지를 띄우는데 사용되는 함수

 

3. FColor

 

FColor Color;

 

언리얼 엔진에서 색상으로 표현하는데 사용되는 구조체

 

FColor::Red;
FColor::Blue;
FColor::Green;
FColor::Black;
FColor::White;
FColor::Cyan;
FColor::Emerald;
FColor::Magenta;
FColor::Orange;
FColor::Purple;
FColor::Silver;
FColor::Transparent;
FColor::Turquoise;
FColor::Yellow;

 

언리얼 엔진에서는 기본적인 색상을 스태틱으로 미리 만들어서 사용자가 일일이 구조체를 생성해서 색상을 만들 필요가 없게 만들어 두었다.

 

 

  1. 다른 이름을 사용해도 상관없지만, 만약 다른 이름을 사용한다면 몇몇 코드 샘플에서의 이름이 달라질 것이다. [본문으로]

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

+ Recent posts