C++와 Unreal Engine으로 3D 게임 개발

C++와 Unreal Engine으로 3D 게임 개발 1-6

jh009 2026. 6. 8. 10:24

1-6 : Tick 함수로 Actor의 Transform 조정하기

1. Transform 속성 이해하기

 

Actor와 Transform

 

액터의 세 가지 속성 (Transform)

- 뷰포트 상에서 x축 (빨간색), y축 (초록색), z축 (파란색)으로 표시

 

1. 위치(Location)

- 액터가 월드에서 어느 지점에 있는지를 나타냄

 

2. 회전(Rotation)

- 액터가 어느 방향, 어떤 각도로 기울어져 있는지를 나타냄

  • Roll: 좌우로 기울어지는 회전 (x축으로 하는 회전)
  • Pitch: 앞뒤 방향의 기울어짐 (y축으로 하는 회전)
  • Yaw: 좌우 방향 회전 (z축으로 하는 회전)

3. 크기(Scale)

- 액터의 크기 비율

- FVector(X, Y, Z) 형태로 표현


FTransform 자료형

 

언리얼 엔진에서 위치, 회전, 스케일을 하나로 묶어 효율적으로 관리하기 위한 구조체

  • Translation: 위치를 표현 FVector
  • Rotation: 회전을 표현 FRotator 
  • Scale3D: 스케일을 표현 FVector

좌표계의 개념

 

월드 좌표계 (World Space)

  • 게임 전체 세계를 기준으로 한 절대적인 좌표계
  • 액터 자체를 이동·회전·스케일할 때 대부분 월드 좌표계를 기준으로 함

로컬 좌표계 (Local Space)

  • 액터 자신이나 부모 액터 (또는 부모 컴포넌트) 의 Transform을 기준으로 한 상대적인 좌표계
  • 계층 구조 (부모-자식 관계) 가 있는 경우, 자식은 부모의 Transform에 종속되어 움직임

부모-자식 컴포넌트 관계

  • 액터에는 여러 컴포넌트가 붙을 수 있음
  • 최상위에 있는 루트 컴포넌트 (Root Component)를 기준으로 다른 컴포넌트들이 Attach (부착) 관계를 맺을 수 있음
  • 부모 액터 (또는 부모 컴포넌트)가 이동·회전·스케일되면 자식들은 상대 좌표값에 따라 함께 이동

부모-자식 관계가 맺어져 있다면

  • GetRelativeTransform(): 부모 기준의 상대 위치·회전·스케일을 가져옴
  • SetRelativeLocation(), SetRelativeRotation(): 부모 기준으로 자식의 위치·회전을 조정

여러 컴포넌트를 한꺼번에 움직이거나, 특정 컴포넌트만 부모 기준으로 움직이게 만들 수 있음


2. C++ 코드로 Transform 다루기

Transform 조정 함수

 

  • SetActorLocation(FVector NewLocation): 액터 위치 이동
  • SetActorRotation(FRotator NewRotation): 액터 회전 (순서대로 Pitch, Yaw, roll 의 값) 
  • SetActorScale3D(FVector NewScale): 액터 스케일 변경
  • GetActorLocation()`, `GetActorRotation(), GetActorScale3D(): 현재 Transform 정보 가져오기
  • SetActorTransform(FTransform NewTransform): 위치·회전·스케일을 한 번에 설정

BeginPlay() 함수에서 Transform 변경

 

Item.cpp

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));
}


3. Tick 함수와 프레임 독립적인 로직 이해하기

게임 프레임 업데이트와 Tick

 

언리얼 엔진은 게임 실행 중 매 프레임마다 여러 작업을 수행

 

1. 렌더링(Rendering): 화면 그리기 (1초에 60프레임, 120프레임 등)

2. 물리 연산: 충돌·중력·마찰 등 물리 엔진 처리

3. 오브젝트 업데이트: 게임 내 액터들의 상태 갱신


Tick 함수 활성화하기

 

Tick() 함수를 사용을 위해선 생성자에서 설정이 필요함

PrimaryActorTick.bCanEverTick = true;
  • bCanEverTick가 false면 엔진은 성능 최적화를 위해 해당 액터의 Tick을 호출하지 않음
  • 불필요한 Tick 호출은 성능에 부담을 줌 → 사용하지 않는다면 false를 명시하여, 최적화 효과와 코드 명확성을 높일 수 있음

DeltaTime

  • 직전 프레임부터 현재 프레임까지 걸린 시간(초)
  • 프레임 레이트가 높을수록 DeltaTime이 작아지고, 낮을수록 DeltaTime이 커짐

4. Tick 함수와 DeltaTime을 활용한 회전 구현하기

회전 속도 변수와 Tick 함수 선언

 

Item.h

protected:
		USceneComponent* SceneRoot;
		UStaticMeshComponent* StaticMeshComp;
		
		// 회전 속도를 나타내는 변수(초당 도(degrees) 단위)
		float RotationSpeed;
		
		virtual void BeginPlay() override;
		virtual void Tick(float DeltaTime) override;
};

Tick 함수에서 DeltaTime으로 회전 구현

#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, 45.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));
		}
}

 

  • FMath::IsNearlyZero : 부동소수점 비교에서 안전하게 0에 가까운지 확인해주는 함수
  • RotationSpeed = 360.0f : 1초에 360도 회전, 180.0f 면 2초에 한 바퀴 회전
  • AddActorLocalRotation() : 액터의 로컬 기준으로 회전을 추가해주는 함수

월드 좌표 기준으로 회전하고 싶다면 → AddActorWorldRotation() 사용