언리얼 엔진에서 콘텐츠를 구성하는 최소 단위의 물체.
액터의 사전 적 의미가 '배우' 듯이, 액터는 게임 월드의 특정 공간에서 자신에게 주어진 역할을 수행하는 물체를 의미한다.
예를 들어 분수대 액터를 만든다고 해보자.
분수대 구조물의 비주얼과 충돌을 담당할 스태틱 메시 컴포넌트와 물의 비주얼을 담당할 스태틱 메시 컴포넌트로 구성된다.
C++에서 액터가 두 개의 스태틱 메시 컴포넌트를 가지려면 분수대 액터의 멤버 변수로 두 개의 UStaticMeshComponent 클래스의 포인터를 선언해줘야 한다.
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "EngineMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"
UCLASS()
class STUDY_API AMyActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AMyActor();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
UStaticMeshComponent* Body;
UStaticMeshComponent* Water;
};
이따 헤더 파일에 선언된 CoreMinimal.h 파일을 EngineMinimal.h파일로 변경해 분수대 액터 클래스가 앞서 살표본 UStaticMeshComponent 클래스 정보를 참조할 수 있도록 설정해줘야 한다.
어떤 C++ 클래스가 언리얼 오브젝트 클래스가 되려면 클래스 선언에 언리얼 엔진이 정의한 특별한 매크로와 규칙을 부여해야 한다.
클래스 선언 매크로 : 해당 클래스가 언리얼 오브젝트임을 선언하기 위한 매크로다. 클래서 선언의 윗줄에 UCLASS 라는 매크로를 선언하고 클래스 내부에는 GENERATED_BODY 매크로를 선언한다.
클래스 이름 접두사 : 접두사는 U와 A가 제공되는데, A는 액터 클래스에 사용하고 U는 액터가 아닌 클래스에 사용한다. 예를 들어 AActor, UStaticMeshComponent 라는 이름을 가진다.
generated.h 헤더 파일
외부 모듈에의 공개 여부
언리얼 실행 환경이 우리가 선언한 객체를 자동으로 관리하게 만들려면 코드에서 UPROPERTY라는 매크로를 사용해 객체를 지정해줘야 한다.
액터의 구축은 클래스의 생성자 코드에서 진행되며, 여기서 스태틱 메시 컴포넌트를 실제로 생성하는 로직을 구현한다. 생성자 코드에서 컴포넌트를 생성하는 용도로 언리얼 엔진은 new가 아닌 CreateDefaultSubobject API라는 특별한 함수를 사용한다.
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;
Body = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BODY"));
Water = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("WATER"));
RootComponent = Body;
Water->SetupAttachment(Body);
}
두 컴포넌트가 생성되면 그 중에서 액터를 대표할 루트 컴포넌트를 지정해야 한다. 분수대 구조물을 담당할 Body 컴포넌트가 대표성을 띠므로, 이를 루트 컴포넌트로 지정하고 Water는 Body의 자식이 되도록 설정한다.
디테일 윈도우에서 컴포넌트의 속성을 편집하기 위해서는 컴포넌트의 선언에 특별한 키워드를 등록해줘야 한다. UPROPERTY 매크로 안에 VisibleAnywhere 라는 키워드를 추가하고 컴파일한다.
액터의 생성자에서 Water 컴포넌트에 SetRelativeLocation을 사용하면 컴포넌트의 기본 위치 값을 변경할 수 있다. 변경할 위치 값은 언리얼 엔진이 제공하는 구조체 FVector를 사용해 전달한다.
언리얼 엔진이 제공하는 대표적인 값 유형은 다음과 같다.
언리얼 엔진에서 게임이 시작되려면 게임의 규칙, 게임에 입장하는 플레이어, 플레이어가 조종하는 액터가 있어야 한다.
이를 대표하는 액터를 각각
게임 모드(GameMode),
플레이어 컨트롤러(PlayerController),
폰(Pawn)
이라고 한다.
게임모드를 만들었다면, 우리가 제작한 ABPawn이 생성되도록 게임 모드의 설정을 변경해본다.
ABGameMode에 생성자 코드를 추가한다.
우리의 로그 매크로와 EngineMininal.h 헤더 파일을 참조하도록 CoreMinimal.h를 ArenaBattle(project name).h로 변경한다.
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "ArenaBattle.h"
#include "GameFramework/GameModeBase.h"
#include "ABGameMode.generated.h"
/**
*
*/
UCLASS()
class ARENABATTLE_API AABGameMode : public AGameModeBase
{
GENERATED_BODY()
public:
AABGameMode();
};
정의 파일로 이동해 생성자를 구현하고 게임 모드의 DefaultPawn 속성에 우리가 제작한 ABPawn을 지정하다. 여기서 주의할 점은 ABPawn 액터를 생성하고 이를 지정하는 것이 아니라 ABPawn 클래스 정보를 지정하는 것이다.
게임 모드에 폰을 지정하는 코드는 다음과 같다.
// Fill out your copyright notice in the Description page of Project Settings.
#include "ABGameMode.h"
#include "ABPawn.h"
AABGameMode::AABGameMode() {
DefaultPawnClass = AABPawn::StaticClass();
}
플레이어가 입장하면 게임 모드는 플레이어에게 폰을 배정해준다.
그런데 게임 모드는 플레이어가 입장할 떄 플레이어 컨트롤러(PlayerController)라는 특별한 액터도 함께 배정한다.
플레이어 컨트롤러 : 게임 세계에서 현실 세계의 프레이어를 대변하는 무형의 액터다. 폰을 조종하는 역할을 맡는다. 플레이어 컨트롤러는 플레이어가 입장할 때 배정되며, 배정된 플레이어 컨트롤러는 변경할 수가 없다.
폰 : 폰은 플레이어 컨트롤러에게 조종당하는 액터다. 플레이어 컨트롤러가 두뇌라면, 폰은 꼭두각시다.
언리얼 엔진에서 플레이어가 플레이어 컨트롤러를 통해 폰을 조종하는 행위를 빙의Possess라고 한다.
플레이어 컨트롤러가 폰을 빙의하면, 앞으로 플레이어의 의지는 플레이어 컨트롤러를 거쳐 폰에게 전달되고 폰은 플레이어의 의지에 따라 움직인다.
언리얼 에디터의 툴바에서 플레이 버튼을 누른다는 것은 현재 만들고 있는 게임에 제작자 플레이어가 입장하는 것이라고 할 수 있다. 플레이어가 입장하면 게임 모드에 의해 다음과 같은 순서로 관련된 액터들이 생성되고 게임플레이를 위한 설정이 갖춰진다.
플레이어가 조종할 수 있는 특수한 액터인 폰은 움직이는 액터에 조종당하는 기능이 추가된 액터다.
폰은 자동차가 될 수 있고 비행기도 될 수 있다.
폰을 제작하기 위해 고려할 요소는 다음과 같다.