이 퀵스타트 가이드에서는 언리얼 엔진에서 C++ 프로젝트를 구성하고 Visual Studio에서 첫 C++ 게임플레이 클래스를 프로그래밍하는 방법을 살펴봅니다. 이 튜토리얼을 완료하면 다음을 수행할 수 있습니다.
- 새 C++ 프로젝트 생성
- C++에서 새 액터 클래스 생성
- 개발 환경에서 시각적 표현 및 함수 기능을 추가하여 C++ 클래스 편집
- 프로젝트 컴파일
- 언리얼 에디터에서 새 액터 테스트
이 가이드는 Visual Studio가 프로그래밍 환경으로 이미 구성되어 있다고 가정합니다. 그렇지 않은 경우 언리얼 엔진용 Visual Studio 구성에서 Visual Studio를 언리얼 엔진 프로그래밍 환경으로 설치 및 구성하는 방법에 대해 알아보세요. 또한 여러분이 이 가이드를 시작하기 전에 언리얼 에디터 를 사용하는 것에 익숙하다고 가정하지만, 편의를 위해 에디터에서 C++ 클래스를 생성 및 관리하는 데 필요한 모든 단계를 거칩니다. 이 가이드의 최종 결과물은 공중에서 천천히 부유하며 계속 회전하는 큐브입니다. 이는 프로그래밍을 위해 개발 환경을 사용하는 방법을 배우면서 테스트할 수 있는 단순한 오브젝트를 제공합니다.
이 가이드는 XCode가 프로그래밍 환경으로 이미 구성되어 있다고 가정합니다. 또한 여러분이 이 가이드를 시작하기 전에 언리얼 에디터 를 사용하는 것에 익숙하다고 가정하지만, 편의를 위해 에디터에서 C++ 클래스를 생성 및 관리하는 데 필요한 모든 단계를 거칩니다. 이 가이드의 최종 결과물은 공중에서 천천히 부유하며 계속 회전하는 큐브입니다. 이는 프로그래밍을 위해 개발 환경을 사용하는 방법을 배우면서 테스트할 수 있는 단순한 오브젝트를 제공합니다.
1. 필수 구성
언리얼 에디터 를 실행합니다. 프로젝트 브라우저(Project Browser) 가 열리면 게임(Games) 프로젝트 카테고리를 클릭하고 기본(Blank) 템플릿을 선택합니다. C++ 를 선택하고 시작용 콘텐츠(Starter Content) 를 활성화해야 합니다. 프로젝트 저장 위치(Save Location) 및 이름(Name) 을 선택하고 프로젝트 생성(Create Project) 을 클릭합니다. 여기에서는 프로젝트를 'QuickStart'로 명명하겠습니다.
그러면 자동으로 필수 C++ 코드만 갖춘 단순한 기본 프로젝트가 생성되고 언리얼 에디터와 Visual Studio 양쪽에서 자동으로 열립니다. 프로젝트를 관리 및 생성하는 것과 관련된 자세한 내용은 프로젝트 브라우저 페이지를 참고하세요.
그러면 자동으로 필수 C++ 코드만 갖춘 단순한 기본 프로젝트가 생성되고 언리얼 에디터와 XCode 양쪽에서 자동으로 열립니다. 프로젝트를 관리 및 생성하는 것과 관련된 자세한 내용은 프로젝트 브라우저 페이지를 참고하세요.
블루프린트 프로젝트는 C++ 프로젝트로 변환할 수 있습니다. C++를 추가하려는 블루프린트 프로젝트가 있는 경우 다음 섹션의 지침에 따라 새 C++ 클래스를 생성하면 에디터에서 코드 환경을 구성합니다. 또한 C++ 프로젝트를 사용하더라도 블루프린트를 사용할 수 있습니다. C++ 프로젝트는 블루프린트 대신 프로젝트의 베이스 클래스를 C++로 구성할 뿐입니다.
2. 새 C++ 클래스 생성
-
언리얼 에디터 에서 파일(File) 드롭다운 메뉴를 클릭하고 새 C++ 클래스...(New C++ Class...) 명령을 선택합니다.
이미지를 클릭하면 전체 크기로 표시됩니다.
-
그러면 부모 클래스 선택(Choose Parent Class) 메뉴가 표시됩니다. 확장할 기존 클래스를 선택하여 해당 기능을 클래스에 추가할 수 있습니다. 월드에 배치할 수 있는 가장 기본적인 오브젝트 타입인 액터(Actor) 를 선택하고 다음(Next) 을 클릭합니다.
이미지를 클릭하면 전체 크기로 표시됩니다.
-
새 액터 이름(Name Your New Actor) 메뉴에서 액터를 FloatingActor 로 명명하고 클래스 생성(Create Class) 을 클릭합니다.
이미지를 클릭하면 전체 크기로 표시됩니다.
언리얼 엔진에서 자동으로 컴파일하고 콘텐츠 브라우저에서 선택된 새 클래스로 리로드합니다. 그러면 프로그래밍 환경에서
FloatingActor.cpp가 자동으로 열립니다.
3. C++ 클래스 편집
이제 C++ 클래스를 생성했으므로 Visual Studio로 전환해서 모드를 편집합니다.
-
Visual Studio 에서 기본적으로 창 왼쪽에 있는 Solution Explorer 로 이동하여
FloatingActor.h를 찾습니다. 이 프로젝트에서는 Games > QuickStart > Source > QuickStart 에 있습니다.
-
FloatingActor.h를 더블클릭하여 열고 텍스트 에디터에서 포커스를 맞춥니다.
이것은 헤더 파일입니다. C++ 클래스의 목차와 같다고 생각하면 됩니다. 새 함수 기능을 빌드하기 전에 이 파일에서 사용할 새 변수 또는 함수 를 선언해야 합니다.
-
AFloatingActor() 선언 아래에 다음 코드를 추가합니다.
UPROPERTY(VisibleAnywhere) UStaticMeshComponent* VisualMesh;여기서 오브젝트의 시각적 표현을 담당할 StaticMeshComponent 를 선언합니다. UProperty 매크로를 사용하는데, 이는 언리얼 에디터에서 이것이 표시되게 합니다. UProperty와 해당 지정자에 대한 자세한 내용은 프로퍼티의 페이지를 참고하세요.
-
이제
FloatingActor.cpp를 열고 다음 코드를 AFloatingActor::AFloatingActor() 내 닫는 대괄호 바로 앞에 추가합니다.VisualMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh")); VisualMesh->SetupAttachment(RootComponent); static ConstructorHelpers::FObjectFinder<UStaticMesh> CubeVisualAsset(TEXT("/Game/StarterContent/Shapes/Shape_Cube.Shape_Cube")); if (CubeVisualAsset.Succeeded()) { VisualMesh->SetStaticMesh(CubeVisualAsset.Object); VisualMesh->SetRelativeLocation(FVector(0.0f, 0.0f, 0.0f)); }이 함수는 생성자 로, 처음 생성되었을 때 스스로를 어떻게 초기화할지 클래스에 알립니다. 추가한 코드는 VisualMesh 레퍼런스를 새 StaticMeshComponent로 채웁니다. 이를 액터에 어태치하고 시작용 콘텐츠 에셋의 큐브 메시로 설정합니다. 코드에서 컴포넌트를 어태치하는 방법에 대한 자세한 내용은 컴포넌트 생성 및 어태치하기 가이드를 참고하세요.
-
다음 코드를 AFloatingActor::Tick(float DeltaTime) 내 닫는 대괄호 바로 앞에 추가합니다.
FVector NewLocation = GetActorLocation(); FRotator NewRotation = GetActorRotation(); float RunningTime = GetGameTimeSinceCreation(); float DeltaHeight = (FMath::Sin(RunningTime + DeltaTime) - FMath::Sin(RunningTime)); NewLocation.Z += DeltaHeight * 20.0f; //높이를 20 인수만큼 스케일 조절 float DeltaRotation = DeltaTime * 20.0f; //초당 20도만큼 회전 NewRotation.Yaw += DeltaRotation; SetActorLocationAndRotation(NewLocation, NewRotation);실시간으로 실행하려는 코드는 틱(Tick) 함수에 추가합니다. 여기에서는 큐브를 위아래로 부유하는 동시에 회전하게 합니다. 틱하는 액터에 대한 자세한 내용은 액터 틱을 참고하세요.
이제 C++ 클래스를 생성했으므로 XCode로 전환해서 모드를 편집합니다.
-
XCode 에서 기본적으로 창 왼쪽에 있는 Project Navigator 로 이동하여
FloatingActor.h를 찾습니다. 이 프로젝트에서는 Games > QuickStart > Source > QuickStart 에 있습니다.
-
FloatingActor.h를 더블클릭하여 열고 텍스트 에디터에서 포커스를 맞춥니다. 이것은 헤더 파일입니다. C++ 클래스의 목차와 같다고 생각하면 됩니다. 새 함수 기능을 빌드하기 전에 이 파일에서 사용할 새 변수 또는 함수 를 선언해야 합니다. -
AFloatingActor() 선언 아래에 다음 코드를 추가합니다.
UPROPERTY(VisibleAnywhere) UStaticMeshComponent* VisualMesh;여기서 오브젝트의 시각적 표현을 담당할 StaticMeshComponent 를 선언합니다. UProperty 매크로를 사용하는데, 이는 언리얼 에디터에서 이것이 표시되게 합니다. UProperty와 해당 지정자에 대한 자세한 내용은 프로퍼티의 페이지를 참고하세요.
-
이제
FloatingActor.cpp를 열고 다음 코드를 AFloatingActor::AFloatingActor() 내 닫는 대괄호 바로 앞에 추가합니다.VisualMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh")); VisualMesh->SetupAttachment(RootComponent); static ConstructorHelpers::FObjectFinder<UStaticMesh> CubeVisualAsset(TEXT("/Game/StarterContent/Shapes/Shape_Cube.Shape_Cube")); if (CubeVisualAsset.Succeeded()) { VisualMesh->SetStaticMesh(CubeVisualAsset.Object); VisualMesh->SetRelativeLocation(FVector(0.0f, 0.0f, 0.0f)); }이 함수는 생성자 로, 처음 생성되었을 때 스스로를 어떻게 초기화할지 클래스에 알립니다. 추가한 코드는 VisualMesh 레퍼런스를 새 StaticMeshComponent로 채웁니다. 이를 액터에 어태치하고 시작용 콘텐츠 에셋의 큐브 메시로 설정합니다. 코드에서 컴포넌트를 어태치하는 방법에 대한 자세한 내용은 컴포넌트 생성 및 어태치하기 가이드를 참고하세요.
-
다음 코드를 AFloatingActor::Tick(float DeltaTime) 내 닫는 대괄호 바로 앞에 추가합니다.
FVector NewLocation = GetActorLocation(); FRotator NewRotation = GetActorRotation(); float RunningTime = GetGameTimeSinceCreation(); float DeltaHeight = (FMath::Sin(RunningTime + DeltaTime) - FMath::Sin(RunningTime)); NewLocation.Z += DeltaHeight * 20.0f; //높이를 20 인수만큼 스케일 조절 float DeltaRotation = DeltaTime * 20.0f; //초당 20도만큼 회전 NewRotation.Yaw += DeltaRotation; SetActorLocationAndRotation(NewLocation, NewRotation);실시간으로 실행하려는 코드는 틱(Tick) 함수에 추가합니다. 여기에서는 큐브를 위아래로 부유하는 동시에 회전하게 합니다. 틱하는 액터에 대한 자세한 내용은 액터 틱을 참고하세요.
4. C++ 코드 컴파일 및 테스트
-
FloatingActor.h및FloatingActor.cpp모두에서 작업을 저장 합니다. 그런 다음 Solution Explorer 에서 프로젝트를 우클릭하고 컨텍스트 메뉴에서 Build 명령을 클릭한 다음 컴파일이 완료될 때까지 기다립니다.
창 하단의 Output 로그에 성공을 뜻하는 'Succeeded'라는 메시지가 표시될 것입니다.
또는 언리얼 에디터 로 돌아가 화면 상단 툴바에서 컴파일(Compile) 버튼을 클릭합니다.
컴파일 전에 작업을 항상 저장해야 합니다. 그렇지 않으면 코드의 변경사항이 적용되지 않습니다.
-
언리얼 에디터 에서 콘텐츠 브라우저 로 돌아가서 C++ Classes 폴더를 열고 FloatingActor 를 찾습니다. 프로젝트와 동일한 이름의 폴더에 있을 것입니다. 이 예시에서는 QuickStart입니다.
-
FloatingActor 를 클릭하고 원근 뷰포트(Perspective Viewport) 로 드래그하여 FloatingActor의 인스턴스를 생성합니다. 월드 아웃라이너(World Outliner) 에서 'FloatingActor1'로 선택되고 해당 프로퍼티가 디테일 패널(Details Panel) 에 표시됩니다.
뷰포트를 탐색하고 월드에 액터를 배치하는 방법에 대한 자세한 내용은 레벨 디자이너 퀵스타트를 참고하세요.
-
FloatingActor1 의 디테일 패널 에서 액터의 위치(Location) 를 -180, 0, 180으로 설정합니다. 그러면 디폴트 씬의 테이블 바로 아래에 배치됩니다.
또는 이동 기즈모를 사용하여 수동으로 옮길 수도 있습니다.
-
화면 상단의 에디터에서 플레이(Play In Editor) 버튼을 누릅니다.
-
FloatingActor.h및FloatingActor.cpp모두에서 작업을 저장 합니다. 그런 다음 화면 상단에서 Product 드롭다운 메뉴를 클릭하고 Build 명령을 선택한 다음 빌드가 완료될 때까지 기다립니다.
창 하단의 Output 로그에 성공을 뜻하는 'Succeeded'라는 메시지가 표시될 것입니다. 또는 언리얼 에디터 로 돌아가 화면 상단 툴바에서 컴파일(Compile) 버튼을 클릭합니다.
컴파일 전에 작업을 항상 저장해야 합니다. 그렇지 않으면 코드의 변경사항이 적용되지 않습니다.
-
언리얼 에디터 에서 콘텐츠 브라우저 로 돌아가서 C++ Classes 폴더를 열고 FloatingActor 를 찾습니다. 프로젝트와 동일한 이름의 폴더에 있을 것입니다. 이 예시에서는 QuickStart입니다.
-
FloatingActor 를 클릭하고 원근 뷰포트(Perspective Viewport) 로 드래그하여 FloatingActor의 인스턴스를 생성합니다. 월드 아웃라이너(World Outliner) 에서 'FloatingActor1'로 선택되고 해당 프로퍼티가 디테일 패널(Details Panel) 에 표시됩니다.
뷰포트를 탐색하고 월드에 액터를 배치하는 방법에 대한 자세한 내용은 레벨 디자이너 퀵스타트를 참고하세요.
-
FloatingActor1 의 디테일 패널 에서 액터의 위치(Location) 를 -180, 0, 180으로 설정합니다. 그러면 디폴트 씬의 테이블 바로 아래에 배치됩니다.
또는 이동 기즈모를 사용하여 수동으로 옮길 수도 있습니다.
-
화면 상단의 에디터에서 플레이(Play In Editor) 버튼을 누릅니다.
5. 최종 결과
이제 큐브가 테이블 위에서 천천히 위아래로 부유하면서 회전하는 모습을 볼 수 있습니다.
축하합니다! 처음으로 C++만 사용하여 액터 클래스를 생성했습니다. 아주 단순한 오브젝트이고 C++ 소스 코드로 수행할 수 있는 작업의 극히 일부에 불과하지만 게임을 위해 C++ 코드를 작성하고, 편집하며, 컴파일하는 기초를 모두 다뤘습니다. 이제 복잡한 게임플레이 프로그래밍에 도전할 준비가 되었습니다. 아래와 같은 과제를 추천합니다.
6. 직접 해보기!
이제 단순한 C++ 액터를 빌드하는 방법을 배웠으므로 좀 더 환경설정 가능하게 만들어보겠습니다. 예를 들어 행동을 제어하는 변수를 추가할 수 있습니다.
FloatingActor.h 에 다음을 추가합니다.
...
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="FloatingActor")
float FloatSpeed = 20.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="FloatingActor")
float RotationSpeed = 20.0f;
...
FloatingActor.cpp 에 다음을 추가합니다.
...
NewLocation.Z += DeltaHeight * FloatSpeed; //높이를 FloatSpeed만큼 스케일 조절
float DeltaRotation = DeltaTime * RotationSpeed; //초당 RotationSpeed만큼 각도 회전
...
이러한 변수를 헤더에 추가하고 cpp에서 DeltaHeight 및 DeltaRotation 스케일 조절에 사용한 플로트 값을 대체하면 액터를 선택했을 때 디테일 패널 에서 부유 및 회전 속도를 편집할 수 있습니다.
위치, 회전 및 스케일을 사용하여 틱 함수에 다른 행동 타입을 추가하면서 실험해볼 수 있습니다.
또한 C++에서 다른 컴포넌트 타입을 어태치하여 보다 복잡한 오브젝트를 생성할 수도 있습니다. 다양한 컴포넌트 타입의 예시는 컴포넌트 생성 및 어태치하기 가이드를 참고하세요. 그리고 파티클 시스템 컴포넌트를 추가하여 부유하는 오브젝트를 좀 더 화려하게 만들어보세요.
마지막으로, 액터 클래스를 콘텐츠 브라우저 에서 우클릭하면 이를 C++ 또는 블루프린트에서 확장하는 옵션이 표시됩니다. 이를 통해 클래스의 새 베리에이션을 생성할 수 있습니다.
이제 FloatingActors의 전체 라이브러리가 준비되었으며, 선택에 따라 다른 메시 또는 파라미터로 교체할 수 있습니다.
샘플 코드
FloatingActor.h
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "FloatingActor.generated.h"
UCLASS()
class QUICKSTART_API AFloatingActor : public AActor
{
GENERATED_BODY()
public:
// 이 액터 프로퍼티의 디폴트 값 설정
AFloatingActor();
UPROPERTY(VisibleAnywhere)
UStaticMeshComponent* VisualMesh;
protected:
// 게임 시작 또는 스폰 시 호출됨
virtual void BeginPlay() override;
public:
// 프레임마다 호출됨
virtual void Tick(float DeltaTime) override;
};
FloatingActor.cpp
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#include "FloatingActor.h"
// 디폴트 값 설정
AFloatingActor::AFloatingActor()
{
// 프레임마다 Tick()을 호출하도록 이 액터를 설정하세요. 필요 없는 경우 퍼포먼스 향상을 위해 이 설정을 끌 수 있습니다.
PrimaryActorTick.bCanEverTick = true;
VisualMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
VisualMesh->SetupAttachment(RootComponent);
static ConstructorHelpers::FObjectFinder<UStaticMesh> CubeVisualAsset(TEXT("/Game/StarterContent/Shapes/Shape_Cube.Shape_Cube"));
if (CubeVisualAsset.Succeeded())
{
VisualMesh->SetStaticMesh(CubeVisualAsset.Object);
VisualMesh->SetRelativeLocation(FVector(0.0f, 0.0f, 0.0f));
}
}
// 게임 시작 또는 스폰 시 호출됨
void AFloatingActor::BeginPlay()
{
Super::BeginPlay();
}
// 프레임마다 호출됨
void AFloatingActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
FVector NewLocation = GetActorLocation();
FRotator NewRotation = GetActorRotation();
float RunningTime = GetGameTimeSinceCreation();
float DeltaHeight = (FMath::Sin(RunningTime + DeltaTime) - FMath::Sin(RunningTime));
NewLocation.Z += DeltaHeight * 20.0f; //높이를 20 인수만큼 스케일 조절
float DeltaRotation = DeltaTime * 20.0f; //초당 20도만큼 회전
NewRotation.Yaw += DeltaRotation;
SetActorLocationAndRotation(NewLocation, NewRotation);
}