[Unreal Engine] Mac에서 Unreal Engine 다루기 1편

Patrick!·2022년 9월 16일
0
post-thumbnail
post-custom-banner

언리얼 엔진4에 요소들의 개념을 알아보자. (여기서 부터 Unity 와 달라진다.)

언리얼 엔진에서 움직이는 캐릭터 하나를 만든다고 가정해보자. (C++ class로 진행)

[C++ 클래스 추가] 를 통해 생성을 진행

그럼 부모 클래스 선택 을 진행해야 하는데 Cheracter, Pawn, Actor 등 다양한 부모 클래스를 선택할 수 있다.

처음 접하는 사람이라면 아마 무턱대로 Cheracter 를 선택할 수 있다. (물론 나도 그랬다.)

하지만 Actor -> Pawn -> Cheractor 순으로 진행하는 것이 Unreal Engine에서는 추천하고 있다.

이유는 간단하다. 바로 Cheracter 를 생성하는 것 보다 Acter, Pawn등을 거치고 Cheracter를 생성하는 것이 기능적으로 더 많은 것을 구현할 수 있기 때문이다.

그럼 Unity와는 어떤 차이가 있는 것인가?

앞서 Unreal Engine 에서는 캐릭터를 하나 만드는데 있어 Actor -> Pawn -> Cheracter 순으로 거쳐서 생성이 된다.
즉, 이 Object가 어떤 역할을 할 것인지 생성 전 부터 설정을 한다는 개념이다.

하지만 Unity의 경우, 생성 후 어떤 역할을 할 것인지 설정한다.

이 부분에 있어 Unreal Engine과 Unity의 차이가 발생한다.

이 차이가 중요한 차이인가?

중요한 차이라고 생각이 될 수 있다고 보는 이유는 이러하다.
작업에 있어 편리함과 불편함의 차이가 각각 있다고 본다.

1. Object 를 생성

Unity의 경우, 간단한 Object 를 생성 후, 이를 필요에 따라 설정하고 관리할 수 있다.

반면에 Unreal Engine의 경우, Object 를 생성하는데 있어 Actor -> Pawn -> Cheracter 를 설정하고 넘어와야 하기에 과정이 길어진다.

2. 기능부여

Unity의 경우, Object에 기능을 하나하나 부여해야하는 단점이 있다.

반면에 Unreal Engine의 경우, Object 를 생성하는데 있어 Actor -> Pawn -> Cheracter 를 거치고 왔기에 해당 Object의 기능이 기초적으로 설정이 된 상태이기에 편리하다.

3. 파일 이름수정 및 삭제

Unity의 경우, 파일의 이름을 변경하거나 파일을 삭제한다면 연관된 부분의 수정 혹은 해당 파일이 import된 부분을 지우면 된다.

놀랍게도 ... Unreal Engine은 이게 적용되지 않는다.

자 그럼 Actor에 대해 알아보자

Actor 란?

인게임에 배치를 할 수 있는 Object를 가리키는 용어이다.

[C++ 클래스 추가] 를 통해 생성을 진행하자.

프로젝트에 코드 추가가 완료되면 ?! 띠리릭 소리와 함께

콘텐츠 브라우저에 MyActor 라는 이름으로 방금 전에 생성한 C++ 클래스 기반의 MyActor Object가 생성된 모습을 확인할 수 있다.

이제 [월드 아웃라이더]를 살펴보자.
이는 Unreal Engine 의 게임 화면에 구성된 모든 Object를 표시한다.

그럼 MyActor를 어떻게 여기에 추가할까 ?

방법은 의외로 간단하다. MyActor를 클릭 후, 화면에 드래그하면 된다.

성공적으로 MyActor를 게임에 추가된 모습을 확인할 수 있다.

하지만 ?! 화면에서 MyActor의 모습을 확인할 수 없다?!

이유는 우리가 MyActor의 기능, 매쉬(형태) 를 정해주지 않았기에 게임에 추가하여도 형태를 알아볼 수 없는 것이다.

그럼 형태를 어떻게 넣어야 하는거지?

이는 형태를 추가하는 C++ Class Code를 작성하는 것이다.
나는 Xcode로 이를 진행하기에 Xcode로 확인해보자.

Xcode 에서 C++ Code 작성하기


위의 사진은 MyActor를 생성하면서 생긴 헤더파일과 CPP파일이다.

생성된 MyActor.h 파일을 살펴보자

UCLASS()
class TESTUNREALENGINE_API AMyActor : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AMyActor();

protected:
    // 게임을 시작하거나 처음 이 Actor가 spawn 될 때, 호출이 되는 기능
	virtual void BeginPlay() override;
    
public:
    // 매 프레임 마다 호출이 되는 기능
	virtual void Tick(float DeltaTime) override;
};

다음과 같은 코드들 중에서 살펴볼 것을 간단하게 보고 넘어가자.

바로 BeginPlay() 와 Tick(float DeltaTime) 이다.

protected:
    virtual void BeginPlay() override;

BeginPlay() => 게임이 시작하거나 처음 Actor가 Map에 Spawn 될 때, 호출되는 기능을 의미한다.

public:
	virtual void Tick(float DeltaTime) override;

Tick(float DeltaTime) => 매 프레임 마다 호출이 되는 기능을 의미한다.

그럼 우리는 Actor에 Mesh를 어떻게 적용하는거지 ?

이제 MyActor class 에 기능을 추가해보는 Code를 작성해보자.

private:
	UStaticMeshComponent* Mesh;

UStaticMeshComponent* 기능을 포인터, Mesh; 라고 선언했다.
여기서 끝나지 않고 추가적으로 작성하는 부분이 있다. (Unreal Engine 한정)

기능을 선언한 부분에 UPROPERTY() 를 선언하는 작업이다.

앞서 MyActor.h 라는 파일의 전체코드를 살펴보면
UCLASS(), GENERATED_BODY(), UPROPERTY() 등 이전에는 보지 못했던 코드가 존재한다.

이들의 역할이 무엇이길래 선언해야 하는건가?

C++ 에는 reflection 이라는 기능이 없다. (C#에는 존재한다.)

Reflection = 객체 지향 프로그램언어에서 런타임에 객체의 형을 결정할 수 있는 능력을 의미

즉, 컴파일러가 이해하는 주석에 가까운 기능이다.
하지만 앞서 본 UCLASS(), GENERATED_BODY(), UPROPERTY() 의 코드들은 Unreal Engine 에서 만든 reflection 개념의 기능이다.

정리하자면!!
UCLASS() = Unreal Engine Class 이런 형태를 나타내며 컴파일러가 런타임때
컴파일러 : MyActor.h 파일은 Unreal Engine Class 구나? 그럼 부가적인 메타 데이터고 같이 기입해줄께!!

이렇게 인식하게 해주는 고급기능인 것이라고 생각하면 된다.

다시 Mesh로 돌아와서 .... (앞서 배울게 많다!!!)

UPROPERTY()
private:
	UStaticMeshComponent* Mesh;

MyActor.h 파일에 Mesh를 선언했으니 MyActor.cpp파일로 넘어가자.

// Sets default values
AMyActor::AMyActor()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

}

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

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

}

MyActor.cpp 파일에서 Mesh를 선언해보자.

기존의 C++ 대로 했었다면 AMyActor::AMyActor() 아래에 다음과 같이 작성할 것이다.

Mesh = new UStaticMeshComponent();

하지만 UPROPERTY() 를 헤더파일에서 선언했기에 이는 unreal engine에서 관리하는 메모리이기에 조금 다르게 cpp파일에 선언해야 한다.

Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEST("MESH"));

기존 C++ 작성법과는 다르게 작성된 모습을 볼 수 있다.
CreateDefaultSubobject(); 는 unreal engine에서 자체적으로 메모리를 관리하기 위해 선언하는 방식이라고 보면 된다.

TEXT("MESH") 에 해당하는 부분은 해시값으로 사용된다. (일종의 이름 개념)

profile
C++와 Unreal Engine / C#과 Unity / Katalon Studio를 통한 자동화 테스트 등을 하루하루 공부한 기록
post-custom-banner

0개의 댓글