Unreal 게임 개발 과정 TIL

Today's I Learning

본캠프 TIL

06.08 Unreal 본캠프) C++ Actor의 Transform 조정

Sunlight__ 2026. 6. 8. 16:27

 

오늘 배운 것

 

1. Actor와 Transfrom

 - Actor는 언리얼 엔진에서 월드에 존재하는 모든 오브젝트를 의미한다.

   건물, 캐릭터, 아이템 등 눈에 보이는 모든 것들이 액터로 표현된다.

 

 - 액터에는 세 가지 중요한 속성이 있다. (이 세 가지 속성을 Transform이라고 한다.)

위치 (Location) 
 : 액터가 월드에서 어느 지점에 있는지를 나타낸다.
FVector(0.0f, 0.0f, 0.0f) 형태로 표현한다.
회전 (Rotation)
 : 액터가 어느 방향을 바라보는지, 어떤 각도로 기울어져 있는지를 나타낸다.
   언리얼 C++ 에서는 주로 FRotator(Pitch, Yaw, Roll) 형태로 표현한다.
      - Roll : 좌우로 기울어지는 회전 (x축을 축으로 하는 회전)
      - Pitch : 앞뒤 방향의 기울어짐 (y축을 축으로 하는 회전)
      - Yaw : 좌우 방향 회전 (z축을 축으로 하는 회전)
스케일 (Scale)
 : 액터의 크기 비율.
   FVector(X, Y, Z) 형태로 표현한다.

 

 - FTransform 자료형

 : 언리얼 엔진에는 위치, 회전, 스케일을 하나로 묶어 효율적으로 관리하기 위한 구조체인 FTransform이 있다.

   - FTransform은 내부적으로 다음 세 요소를 보관한다.

      : Translation : 위치를 표현하는 FVector

      : Rotation : 회전을 표현하는 FRotator

      : Scale3D : 스케일을 표현하는 FVector

   FTransform을 활용하면 위치/회전/스케일을 한 번에 다룰 수 있어, Transfrom 관련 연산을 보다 편리하게 처리할 수 있다.

 

 - 좌표계의 개념

 : 월드 좌표계 (World Space)

   - 게임 전체를 기준으로 한 절대적인 좌표계이다.

   - SetActorLocation(), GetActorLocation() 처럼 액터 자체를 이동/회전/스케일할 때 대부분 월드 좌표계를 기준으로 한다.

 : 로컬 좌표계 (Local Space)

   - 액터 자신이나 부모 액터 (또는 부모 컴포넌트)의 Transform 기준으로 한 상대적인 좌표계이다.

   - 계층 구조 (부모-자식 관계)가 있는 경우, 자식은 부모의 Transform에 종속되어 움직인다.

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

      : GetRelativeTransform() : 부모 기준의 상대 위치/회전/스케일을 가져온다.

      : SetRelativeLocation(), SetRelativeRotation() : 부모 기준으로 자식의 위치/회전/스케일을 조정

 

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

 - Transform 조정 함수

 : 게임 로직에서 액터의 Transform을 변경하고 싶다면, C++ 또는 블루프린트 함수를 사용한다.

   대표적인 함수들은 아래와 같다.

- SetActorLocation(FVector NewLocation) : 액터 위치 이동
- SetActorRotation(FRotator NewRotation) : 액터 회전
- SetActorScale3D(FVector NewScale) : 액터 스케일 변경
- GetActorLocation(), GetActorRotation(), GetActorScale3D() : 현재 Transform 정보 가져오기
- SetActorTransform(FTransform NewTransform) : 위치/회전/스케일을 한 번에 설정

 

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

 - 게임 프레임 업데이트와 Tick

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

      - 렌더링(Rendering) : 화면 그리기 (일반적으로 1초에 60프레임, 120프레임 등)

      - 물리 연산 : 충돌/중력/마찰 등 물리 엔진 처리

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

 : 특정 액터가 "매 프레임마다" 수행할 로직이 있다면, 언리얼 엔진은 그 액터의 Tick(float DeltaTime) 함수를 매 프레임 호출한다.

 - Tick 함수 활성화 하기

 : 액터를 생성할 때 기본적으로 Tick() 함수를 사용하려면, 아래와 같이 생성자에서 설정해야 한다.

PrimaryActorTick.bCanEverTick = true;

 

 : bCanEverTick가 false면 엔진은 성능 최적화를 위해 해당 액터의 Tick을 호출하지 않는다.

  불필요한 Tick 호출은 성능에 부담을 주기에, 사용하지 않는다면 false를 명시하여 최적화 효과코드 명확성을 높일 수 있다.

 - DeltaTime 이란?

 : Tick(float DeltaTime) 함수에서 Deltatime"직전 프레임부터 현재 프레임까지 걸린 시간(초)" 이다.

      - 60 FPS경 : DeltaTime ≈ 1/60초 ≈ 0.0167초

      - 120 FPS경 : DeltaTime ≈ 1/120ch ≈ 0.0083초

   프레임 레이트가 높을 수록 Deltatime이 작아지고, 낮을수록 DeltaTime이 커진다.

 - DeltaTime을 활용한 프레임 독립적인 움직임

 : 단순히 "매 프레임마다 X 좌표를 1씩 증가" 시키면, FPS가 높을 수록 더 빨리 움직여 게임 체감 속도가 달라지게 된다.

   이를 방지하려면 DeltaTime을 곱해서 초 단위 기준으로 이동/회전을 계산해야 한다.

      ex) 초당 100 만큼 이동하고 싶다면 : 100 * DeltaTime을 매 프레임마다 더해준다.

         - 60  FPS -> 한 프레임 당 1.67씩 이동

         - 120 FPS -> 한 프레임 당 0.83씩 이동

 

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

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

 : 이동 뿐 아니라 회전도 마찬가지로 DeltaTime을 곱해주면, 초당 일정 각도로 회전하는 것을 쉽게 구현할 수 있다.

// 회전 속도를 나타내는 변수(초당 도(degrees) 단위)
float RotationSpeed;

virtual void Tick(float DeltaTime) override;

item.h

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

  #include "Item.h"

AItem::AItem()
{
   // Tick 함수를 켜줍니다.
   PrimaryActorTick.bCanEverTick = true;

   // 기본 회전 속도 (1초에 90도 회전)
   RotationSpeed = 90.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()은 액터의 로컬 기준으로 회전을 추가해주는 함수이다.

 

오늘 배운 것에서 개인적으로 중요하다고 생각하는 것

Deltatime
 : 직전 프레임부터 현재 프레임까지 걸린 시간(초)