Actor (액터)는 언리얼 엔진에서 게임 세계(월드)에 존재하는 모든 오브젝트를 의미한다. 건물, 캐릭터, 아이템 등 눈에 보이는 모든 것들이 액터로 표현된다.
액터에는 세 가지 중요한 속성이 있다.
1. 위치(Location)
2. 회전(Rotation)
3. 크기(Scale)
- 이 세 가지 속성을 Transform이라고 부르며, 뷰포트 상에서 보통 x축 (빨간색), y축 (초록색), z축 (파란색)으로 표시된다.

위치 (Location)
FVector(100.0f, 200.0f, 300.0f)라면 월드의 x축으로 100, y축으로 200, z축으로 300만큼 떨어진 위치를 의미한다.회전 (Rotation)
FRotator(Pitch, Yaw, Roll) 형태로 표현한다.스케일 (Scale)
FVector(X, Y, Z) 형태로 표현되며, 예) FVector(2.0f, 2.0f, 2.0f)는 기본 크기의 2배를 의미한다.FTransform이 있다.FTransform은 내부적으로 다음 세 요소를 보관한다.FVectorFRotatorFVectorFTransform을 활용하면 위치·회전·스케일을 한 번에 다룰 수 있어, Transform 관련 연산을 보다 편리하게 처리할 수 있다.SetActorLocation(), GetActorLocation()처럼 액터 자체를 이동·회전·스케일할 때 대부분 월드 좌표계를 기준으로 한다.GetRelativeTransform(): 부모 기준의 상대 위치·회전·스케일을 가져옴SetRelativeLocation(), SetRelativeRotation(): 부모 기준으로 자식의 위치·회전을 조정언리얼 에디터에서 액터를 선택하면 3D Gizmo(화살표, 회전 핸들, 스케일 핸들)을 마우스로 직접 움직여서 위치·회전·스케일을 조정할 수 있다.
게임 로직에서 액터의 Transform을 변경하고 싶다면, C++ 또는 블루프린트 함수를 사용합니다. 대표적인 함수들은 아래와 같다.
SetActorLocation(FVector NewLocation): 액터 위치 이동SetActorRotation(FRotator NewRotation): 액터 회전SetActorScale3D(FVector NewScale): 액터 스케일 변경GetActorLocation(), GetActorRotation(), GetActorScale3D(): 현재 Transform 정보 가져오기SetActorTransform(FTransform NewTransform): 위치·회전·스케일을 한 번에 설정
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "AItem.generated.h"
UCLASS()
class SPARTAPROJECT_API AItem : public AActor
{
GENERATED_BODY()
public:
AItem();
protected:
USceneComponent* SceneRoot;
UStaticMeshComponent* StaticMeshComp;
virtual void BeginPlay() override;
};
Item.h
#include "AItem.h"
AItem::AItem()
{
SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
SetRootComponent(SceneRoot);
StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
StaticMeshComp->SetupAttachment(SceneRoot);
static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/Game/Resources/Props/SM_Chair.SM_Chair"));
if (MeshAsset.Succeeded())
{
StaticMeshComp->SetStaticMesh(MeshAsset.Object);
}
static ConstructorHelpers::FObjectFinder<UMaterial> MaterialAsset(TEXT("/Game/Resources/Materials/M_Metal_Gold.M_Metal_Gold"));
if (MaterialAsset.Succeeded())
{
StaticMeshComp->SetMaterial(0, MaterialAsset.Object);
}
}
void AItem::BeginPlay()
{
Super::BeginPlay();
// 위치, 회전, 스케일 설정하기
// (300, 200, 100) 위치로 이동
SetActorLocation(FVector(300.0f, 200.0f, 100.0f));
// Yaw 방향으로 45도 회전
SetActorRotation(FRotator(0.0f, 45.0f, 0.0f));
// 모든 축을 2배로 스케일
SetActorScale3D(FVector(2.0f));
}
Item.cpp
BeginPlay()는 액터가 월드에 배치된 후 초기화가 끝나면 자동으로 호출됩니다. 여기서 SetActorLocation 등으로 Transform을 바꾸면 게임 시작과 동시에 적용된다.SetActorScale3D(FVector(2.0f))와 같이 스케일 값을 통일하면, 모든 축 (x, y, z)이 같은 비율로 확대·축소된다.
참고
위 코드를 이렇게 쓸 수도 있다.FVector NewLocation(300.0f, 200.0f, 100.0f); FRotator NewRotation(0.0f, 90.0f, 0.0f); FVector NewScale(2.0f); FTransform NewTransform(NewRotation, NewLocation, NewScale); SetActorTransform(NewTransform);
Tick(float DeltaTime) 함수를 매 프레임 호출해준다.Tick() 함수를 사용하려면, 아래와 같이 생성자에서 설정해야 한다.PrimaryActorTick.bCanEverTick = true;
bCanEverTick가 false면 엔진은 성능 최적화를 위해 해당 액터의 Tick을 호출하지 않는다.false를 명시해주어 최적화 효과와 코드 명확성을 높이자.Tick(float DeltaTime) 함수에서 DeltaTime은 “직전 프레임부터 현재 프레임까지 걸린 시간(초)”입니다.DeltaTime ≈ 1/60초 ≈ 0.0167초DeltaTime ≈ 1/120초 ≈ 0.0083초100 * DeltaTime을 매 프레임마다 더해줌Item 클래스에 회전 속도 변수를 추가해보자.#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Item.generated.h"
UCLASS()
class SPARTAPROJECT_API AItem : public AActor
{
GENERATED_BODY()
public:
AItem();
protected:
USceneComponent* SceneRoot;
UStaticMeshComponent* StaticMeshComp;
// 회전 속도를 나타내는 변수(초당 도(degrees) 단위)
float RotationSpeed;
virtual void BeginPlay() override;
virtual void Tick(float DeltaTime) override;
};
Item.h
#include "Item.h"
AItem::AItem()
{
SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
SetRootComponent(SceneRoot);
StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
StaticMeshComp->SetupAttachment(SceneRoot);
static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/Game/Resources/Props/SM_Chair.SM_Chair"));
if (MeshAsset.Succeeded())
{
StaticMeshComp->SetStaticMesh(MeshAsset.Object);
}
static ConstructorHelpers::FObjectFinder<UMaterial> MaterialAsset(TEXT("/Game/Resources/Materials/M_Metal_Gold.M_Metal_Gold"));
if (MaterialAsset.Succeeded())
{
StaticMeshComp->SetMaterial(0, MaterialAsset.Object);
}
// Tick 함수를 켜줍니다.
PrimaryActorTick.bCanEverTick = true;
// 기본 회전 속도 (1초에 90도 회전)
RotationSpeed = 90.0f;
}
void AItem::BeginPlay()
{
Super::BeginPlay();
SetActorLocation(FVector(300.0f, 200.0f, 100.0f));
SetActorRotation(FRotator(0.0f, 90.0f, 0.0f));
SetActorScale3D(FVector(2.0f));
}
void AItem::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// RotationSpeed가 0이 아니라면 회전 처리
if (!FMath::IsNearlyZero(RotationSpeed))
{
// 초당 RotationSpeed만큼, 한 프레임당 (RotationSpeed * DeltaTime)만큼 회전
AddActorLocalRotation(FRotator(0.0f, RotationSpeed * DeltaTime, 0.0f));
}
}
Item.cpp
FMath::IsNearlyZero는 부동소수점 비교에서 안전하게 0에 가까운지 확인해주는 함수이다.RotationSpeed = 360.0f면 1초에 한 바퀴(360도) 회전, 180.0f면 2초에 한 바퀴 회전하게 된다.AddActorLocalRotation()은 액터의 로컬 기준으로 회전을 추가해주는 함수이다.AddActorWorldRotation()을 사용할 수도 있다.RotationSpeed 값에 따라 회전 속도가 달라지는 것을 테스트 해볼 수도 있다.
FRotator(Pitch, Yaw, Roll) 부분을 적절히 수정하면 된다.AddActorWorldOffset()에 DeltaTime을 곱해주면 초당 이동 거리를 일정하게 만들 수 있다.Item 클래스 다시보기**AItem 클래스의 헤더(Item.h)입니다. 이미 클래스 선언에 리플렉션 관련 매크로가 포함되어 있다.#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Item.generated.h" // 반드시 마지막에 위치해야 한다.
UCLASS()
class SPARTAPROJECT_API AItem : public AActor
{
GENERATED_BODY()
public:
AItem();
protected:
USceneComponent* SceneRoot;
UStaticMeshComponent* StaticMeshComp;
float RotationSpeed;
virtual void BeginPlay() override;
virtual void Tick(float DeltaTime) override;
};
Item.h
#include "Item.generated.h"#include 구문 아래에 위치해야 한다. (다른 #include보다 아래에 오지 않으면 빌드 에러 발생 위험이 있다.)UCLASS()GENERATED_BODY()UCLASS() 매크로의 주요 지정자**UCLASS() 매크로는 클래스를 리플렉션 시스템에 등록하면서, 추가적으로 몇 가지 옵션 (지정자)을 설정할 수 있다.
기본 동작
- 만약 UCLASS()에 옵션을 주지 않으면, 블루프린트에서 상속이 가능하고 변수로 참조가 가능한 형태로 등록된다. 즉, 내부적으로 Blueprintable, BlueprintType과 동일한 효과를 가지게 된다.
즉
UCLASS(Blueprintable, BlueprintType)=UCLASS()이다
주요 옵션
BlueprintableNotBlueprintableBlueprintType

UPROPERTY() 매크로의 주요 지정자**UPROPERTY()에는 여러 지정자를 작성해, 에디터에서의 표시 여부나 Blueprint 접근성, 읽기/쓰기 권한 등을 자세하게 설정할 수 있다. 아래는 자주 쓰이는 대표적인 지정자들이다.VisibleAnywhere: 읽기 전용으로 표시되며, 수정은 불가능EditAnywhere: 클래스 기본값, 인스턴스 모두에서 수정 가능EditDefaultsOnly: 클래스 기본값에서만 수정 가능EditInstanceOnly: 인스턴스에서만 수정 가능BlueprintReadWrite: Blueprint 그래프에서 Getter/Setter로 값을 읽거나 쓸 수 있다.BlueprintReadOnly: Blueprint 그래프에서 Getter 핀만 노출되어, 읽기만 가능하다.meta=(ClampMin="0.0"): 에디터에서 변수 입력 시 최소값을 제한할 수 있다.meta=(AllowPrivateAccess="true"): 해당 멤버가 private로 선언되어 있어도, 에디터나 Blueprint에서 접근할 수 있도록 허용한다다.Item 클래스 변수 리플렉션 등록Item 클래스 변수들에 대해 UPROPERTY() 매크로를 적용한 모습이다.#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Item.generated.h"
UCLASS()
class SPARTAPROJECT_API AItem : public AActor
{
GENERATED_BODY()
public:
AItem();
protected:
// Root Scene Component, 에디터에서 볼 수만 있고 수정 불가
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Item|Components")
USceneComponent* SceneRoot;
// Static Mesh, 에디터와 Blueprint에서 수정 가능
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Item|Components")
UStaticMeshComponent* StaticMeshComp;
// 회전 속도, 클래스 기본값만 수정 가능
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Item|Properties")
float RotationSpeed;
virtual void BeginPlay() override;
virtual void Tick(float DeltaTime) override;
};
item.h
#include "Item.h"
AItem::AItem()
{
SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
SetRootComponent(SceneRoot);
StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
StaticMeshComp->SetupAttachment(SceneRoot);
PrimaryActorTick.bCanEverTick = true;
RotationSpeed = 90.0f;
}
void AItem::BeginPlay()
{
Super::BeginPlay();
}
void AItem::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (!FMath::IsNearlyZero(RotationSpeed))
{
AddActorLocalRotation(FRotator(0.0f, RotationSpeed * DeltaTime, 0.0f));
}
}
Item.cpp
UPROPERTY() 지정자를 설정해두면, Blueprint 클래스를 통해 해당 변수들을 에디터 내에서 쉽게 조정할 수 있게 된다.BP_Item (Item을 부모로 하는 블루프린트)에 들어간다.RotationSpeed를 확인할 수 있다.
RotationSpeed 값만 조정해도, 코드를 다시 빌드하지 않고 오브젝트의 회전 속도를 직접 바꿔볼 수 있다.StaticMeshComp나 Material 속성도 에디터에서 선택해 바꿀 수 있다.


UPROPERTY()가 멤버 변수를 리플렉션 시스템에 등록한다면,UFUNCTION()은 멤버 함수를 등록한다.UFUNCTION() 매크로를 사용한다.UFUNCTION() 매크로의 주요 지정자BlueprintCallableBlueprintPureBlueprintImplementableEventUFUNCTION()에 지정자를 하나도 쓰지 않았다면?UPROPERTY()와 마찬가지로, 함수가 언리얼 리플렉션에 등록되긴 하지만, 특별히 Blueprint에 노출되지는 않는다.Item 클래스 함수 리플렉션 등록Item 클래스에 여러 함수를 정의하고, UFUNCTION() 매크로를 통해 각각 다른 방식으로 블루프린트에 노출한 코드이다.#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Item.generated.h"
UCLASS()
class SPARTAPROJECT_API AItem : public AActor
{
GENERATED_BODY()
public:
AItem();
protected:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Item|Components")
USceneComponent* SceneRoot;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item|Components")
UStaticMeshComponent* StaticMeshComp;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Item|Properties")
float RotationSpeed;
virtual void BeginPlay() override;
virtual void Tick(float DeltaTime) override;
// 함수를 블루프린트에서 호출 가능하도록 설정
UFUNCTION(BlueprintCallable, Category="Item|Actions")
void ResetActorPosition();
// 블루프린트에서 값만 반환하도록 설정
UFUNCTION(BlueprintPure, Category = "Item|Properties")
float GetRotationSpeed() const;
// C++에서 호출되지만 구현은 블루프린트에서 수행
UFUNCTION(BlueprintImplementableEvent, Category = "Item|Event")
void OnItemPickedUp();
};
Item.h
#include "Item.h"
AItem::AItem()
{
SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
SetRootComponent(SceneRoot);
StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
StaticMeshComp->SetupAttachment(SceneRoot);
PrimaryActorTick.bCanEverTick = true;
RotationSpeed = 90.0f;
}
void AItem::BeginPlay()
{
Super::BeginPlay();
// 블루프린트에서 구현한 함수를 C++에서 호출함
OnItemPickedUp();
}
void AItem::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (!FMath::IsNearlyZero(RotationSpeed))
{
AddActorLocalRotation(FRotator(0.0f, RotationSpeed * DeltaTime, 0.0f));
}
}
// BlueprintCallable 함수 구현
void AItem::ResetActorPosition()
{
// (0, 0, 0) 위치로 되돌립니다.
SetActorLocation(FVector::ZeroVector);
}
float AItem::GetRotationSpeed() const
{
return RotationSpeed;
}
Item.cpp
BP_Item)의 Event Graph 창에서 우클릭한 뒤, 함수 이름을 검색하면 아래와 같이 노드가 노출된다.
ResetActorPosition → BlueprintCallable로 선언했으므로, 노드로 실행(Exec)할 수 있다.GetRotationSpeed → BlueprintPure로 선언했으므로, 단순히 값만 반환하는 Getter 노드로 사용된다.OnItemPickedUp → BlueprintImplementableEvent로 선언했으므로, 이벤트 그래프 안에서 구현한 내용을 C++에서 OnItemPickedUp()를 호출함으로써 실행할 수 있다.OnItemPickedUp은 C++에선 함수 이름만 존재하고 실제 코드는 없다. 대신, Blueprint에서 이벤트 그래프를 통해 시각적 로직으로 구현해두면, C++에서 OnItemPickedUp()를 부르는 순간 그 이벤트가 실행된다.