언리얼에서는 왜 물체 rotation에 Roll, Pitch, Yaw라는 용어를 사용할까?
👉 비행기 기준으로 3축 회전을 정의한 용어라서
👉 Roll / Pitch / Yaw라고 부름
✈️ 1️⃣ 어디서 나온 말이냐
항공공학에서 시작됨.
👉 비행기가 공중에서 움직일 때:
- 좌우로 기울고
- 위아래로 들리고
- 방향을 바꾸고
👉 이걸 3가지 회전으로 정의한 것!
🎯 2️⃣ 각각 의미
🔹 Roll (롤)
👉 “좌우로 기울기”
- 날개 기준 회전
- 옆으로 눕는 느낌
왼쪽으로 기울기 / 오른쪽으로 기울기
🔹 Pitch (피치)
👉 “앞뒤로 들기”
- 기수(코) 위/아래
위로 상승 / 아래로 하강
🔹 Yaw (요)
👉 “좌우 방향 회전”
- 좌우로 방향 틀기
왼쪽으로 턴 / 오른쪽으로 턴
Transform 속성 이해하기
Actor와 Transform
- Actor는 게임에 존재하는 모든 오브젝트를 의미
- Transform은 액터의 3가지 속성
- 위치(Location)
- FVector(100.0f, 200.0f, 300.0f)라면 x축으로 100, y축으로 200, z축으로 300만큼 떨어진 위치
- 회전(Rotation)
- FRotator(Pitch, Yaw, Roll) 형태로 표현
- Roll: 좌우로 기울어지는 회전(X축을 축으로 함)
- Pitch: 앞뒤 방향으로 기울어지는 회전(Y축을 축으로 함)
- Yaw: 좌우 방향 회전(z축을 축으로 하는 회전)
- FRotator(Pitch, Yaw, Roll) 형태로 표현
- 크기(Scale)
- FVector(2.0f, 2.0f, 2.0f)라면 x, y, z축 순으로 기본 크기의 2배를 의미하게 됨
- 전부 같은 비율로 증가시키려면 FVector(2.0f)로 사용 가능
- 위치(Location)
FTransform 자료형
언리얼 엔진에는 위치, 회전, 스케일을 하나로 묶은 구조체인 FTransform이 있다.
- FTransform의 세 가지 요소
- Translation: 위치를 표현하는 FVector
- Rotation: 회전을 표현하는 FRotator
- Scale3D: 스케일을 표현하는 FVector

Transform 메서드
- GetRelativeTransform(): 부모 기준의 상대 위치/회전/스케일을 가져옴
- SetRelativeLocation(), SetRelativeRotation(): 부모 기준으로 자식의 위치/회전을 조정
- SetActorLocation(FVector NewLocation) : 액터 위치 이동
- SetActorRotation(FRotator NewRotation) : 액터 회전
- SetActorScale3D(FVector NewScale) : 액터 스케일 변경
- GetActorLocation() , GetActorRotation() , GetActorScale3D() : 현재 Transform 정보 가져오기 SetActorTransform(FTransform NewTransform) : 위치·회전·스케일을 한 번에 설정
코드 예시
void AItem::BeginPlay()
{
Super::BeginPlay();
SetActorLocation(FVector(300.f,200.f,100.f));
SetActorRotation(FRotator(0.f,90.f,0.f)); // pitch, yaw, roll
SetActorScale3D(FVector(2.0f, 2.0f, 2.0f)); // FVector(2.0f) 라고만 해도 됨
FVector NewLocation(300.f, 200.f, 100.f);
FRotator NewRotation(0.f, 90.f, 0.f);
FVector NewScale(2.0f);
FTransform NewTransform(NewRotation, NewLocation, NewScale);
SetActorTransform(NewTransform); // 위쪽을 똑같이 구현한 것
}
Tick 함수와 프레임
언리얼 엔진은 게임 실행 중 매 프레임마다 여러 작업을 수행
- 렌더링: 화면 그리기(일반적으로 1초에 60프레임, 120프레임 등
- 물리 연산: 충돌/중력/마찰 등 물리 엔진 처리
- 오브젝트 업데이트: 게임 내 액터들의 상태 갱신
특정 액터가 매 프레임마다 수행할 로직이 있다면, 언리얼 엔진은 그 액터의 Tick(float DeltaTime) 함수를 매 프레임 호출한다.
Tick 함수 활성화
Tick() 함수를 사용하려면, 생성자에서 설정해주어야한다.
PrimaryActorTick.bCanEverTick = true;
DeltaTime
- Tick(float DeltaTime) 함수에서 DeltaTime은 직전 프레임부터 현재 프레임까지 걸린 시간이다.
- 60FPS: DeltaTime은 1/60초, 즉 0.0167초 가량
- 120FPS: DeltaTime은 1/120초, 즉 0.0083초 가량
- 프레임 레이트가 높을수록 DeltaTime이 작아지고, 낮을수록 DeltaTime이 커진다.
- FPS에 따라 게임 체감 속도가 달라지기 때문에, DeltaTime을 곱하여 평준화해주어야한다.
- 초당 100만큼 이동하려면 100*DeltaTime을 매 프레임마다 더해줌
- 60 FPS: 한 프레임당 1.67씩 이동, 60 프레임 곱하면 100
- 120 FPS: 한 프레임당 0.83씩 이동, 120 프레임 곱하면 100
- 초당 100만큼 이동하려면 100*DeltaTime을 매 프레임마다 더해줌
Tick과 DeltaTime을 활용한 회전 구현
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h" // 언리얼 엔진의 기본 타입
#include "GameFramework/Actor.h" // 액터에 대한 정보를 가지고 있는 헤더파일
#include "Item.generated.h" // 리플렉션 시스템에 관련한 헤더 파일
UCLASS() // 리플렉션 시스템에 등록해주는 키워드
class SPARTAPROJECT_API AItem : public AActor // A 접두어는 Actor계열이라는 의미이다. Object는 U, 구조체는 F, Enum은 E
{
GENERATED_BODY() // UCLASS와 같은 역할의 매크로
public:
// Sets default values for this actor's properties
AItem();
protected:
USceneComponent* SceneRoot;
UStaticMeshComponent* StaticMeshComp;
float RotationSpeed;
virtual void BeginPlay() override;
virtual void Tick(float DeltaTime) override;
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "Item.h"
// Sets default values
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<UMaterialInterface> MaterialAsset(TEXT("/Game/Resources/Materials/M_Metal_Steel.M_Metal_Steel"));
if (MaterialAsset.Succeeded())
{
StaticMeshComp->SetMaterial(0, MaterialAsset.Object);
}
PrimaryActorTick.bCanEverTick = true; // 사용을 안 한다면 false로 해놓기
RotationSpeed = 90.0f;
}
void AItem::BeginPlay()
{
Super::BeginPlay();
SetActorLocation(FVector(300.f,200.f,100.f));
SetActorRotation(FRotator(0.f, 90.f,0.f)); // pitch, yaw, roll
SetActorScale3D(FVector(2.0f, 2.0f, 2.0f)); // FVector(2.0f) 라고만 해도 됨
//FVector NewLocation(300.f, 200.f, 100.f);
//FRotator NewRotation(0.f, 90.f, 0.f);
//FVector NewScale(2.0f);
//FTransform NewTransform(NewRotation, NewLocation, NewScale);
//SetActorTransform(NewTransform);
}
void AItem::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (!FMath::IsNearlyZero(RotationSpeed)) // FMath::IsNearlyZero(float): float값의 오차를 보정하여 0에 근접한지 판단해주는 함수
{
AddActorLocalRotation(FRotator(0.0f, RotationSpeed * DeltaTime, 0.0f));
}
}
'게임 개발 > 학습 일지' 카테고리의 다른 글
| TA 코스 1주차 과제 - AI로 3D 모델링 생성 후 언리얼에 적용하기 (0) | 2026.04.13 |
|---|---|
| 언리얼 C++ - 리플렉션 시스템 활용 (0) | 2026.04.12 |
| 언리얼 C++ - Actor의 라이프 사이클 (0) | 2026.04.11 |
| 언리얼 C++ - Actor 클래스 생성 및 삭제 (0) | 2026.04.11 |
| 언리얼 엔진 심화 1주차 - 리플렉션/UHT/UBT/CDO (0) | 2026.04.10 |