언리얼엔진5 공부

언리얼엔진 C++ 챕터1 - 4. Tick 함수로 Actor의 Transform 조정하기

Client Side 2025. 9. 17. 17:04

1. Transform 속성 이해하기

 

1-1. 액터의 트랜스폼

1) 위치(Location) : FVector(100.0f, 200.0f, 300.0f)  x축, y축, z축의 순서.

2) 회전(Rotation) : FRotation(Pitch, Yaw, Roll) y축, z축, x축의 순서.

                             - Pitch : 앞뒤 방향으로 기울어짐 (y축 회전)

                             - Roll : 좌우로 기울어짐 (x축 회전)

                             - Yaw : 좌우 방향 회전 (z축 회전)

3) 스케일(Scale) : FVector(X, Y, Z) 형태로 표현되며, 하나의 인자만 넣으면 3개의 인자가 같이 적용된다.

 

1-2. FTransfom

: 위치, 회전, 스케일을 하나로 묶어 효율적으로 관리하기 위한 구조체.

  • FTransform의 세 가지 요소
    • Translation : 위치를 표현한느 FVector
    • Rotation : 회전을 표현하는 FRotator
    • Scale3D : 스케일을 표현하는 FVector

FVector NewLocation(300.0f, 200.0f, 100.0f);
FRotator NewRotator(0.0f, 90.0f, 0.0f);
FVector NewScale(0.0f, 90.0f, 0.0f);

FTransform NewTransform(NewRotator, NewLocation, NewScale); // 회전 -> 위치 -> 크기  순서

SetActorTransform(NewTransform); // 트랜스폼 세 가지를 한꺼번에 관리하는 방법.

 

 

1-3.  좌표계의 개념

  • 월드좌표계(World Space)
    • 게임 전체 세계를 기준으로 한 절대적인 좌표계.
    • SetActorLocation(), GetActorLocation() 처럼 액터 자체를 이동 회전 스케일 할 때 대부분 월드 좌표계를 기준으로 한다.
  • 로컬좌표계(Local Space)
    • 액터 자신이나 부모 액터 (또는 부모 컴포넌트)의 Transform을 기준으로 한 상대적인 좌표계.
    • 계층 구조 (부모-자식 관계)가 있는 경우, 자식은 부모의 Transform에 종속되어 움직인다.

 

1-4. 부모-자식 컴포넌트 관계

  • 액터에는 여러 컴포넌트가 붙을 수 있으며, 최상위에 있는 루트 컴포넌트를 기준으로 다른 컴포넌트들이 Attach관계를 맺을 수 있다.
  • 부모 액터가 이동 회전 스케일되면 자식들은 상대 좌표값에 따라 함께 이동한다.
  • 부모-자식 관계가 맺어져 있다면,
    • GetRelativeTranform() : 부모 기준의 상대 위치, 회전, 스케일을 가져옴.
    • SetRelativeLocation(), SetRelativeRotation() : 부모 기준으로 자식의 위치, 회전을 조정.
  • 이처럼 로컬 좌표계를 적절히 활용하면, 여러 컴포넌트를 한꺼번에 움직이거나, 특정 컴포넌트만 부모 기준으로 움직이게 만들 수 있다.

 

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

2-1. Transform 조정 함수

  • SetActorLocation(FVector NewLocation) : 액터 위치 이동
  • SetActorRotation(FRotator NewRotation) : 액터 회전
  • SetActorScale3D(FVector NesScale) : 액터 스케일 변경
  • GetActorLocation(), GetActorRotation(), GetActorScale3D() : 현재 Transform정보 가져오기
  • SetActorTransform(FTransform NewTransform) : 위치, 회전, 스케일을 한 번에 설정.
  • SetActorScale3D(FVector(2.0f))와 같이 스케일 값을 통일하면, 모든 축 (x, y, z)이 같은 비율로 확대·축소된다.
void AItem::BeginPlay()
{
	Super::BeginPlay();
	SetActorScale3D(FVector(2.0f, 4.0f, 3.0f));
	SetActorLocation(FVector(0.0f, 0.0f, 20.0f));
	SetActorRotation(FRotator(2.0f, 1.0f, 1.5f));

}

 

이렇게 입력하면 게임이 시작될 때 액터의 Transform이 변경된다.

 

 

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

3-1. 게임 프레임 업데이트와 Tick

  • 언리얼 엔진은 게임 실행 중 매 프레임마다 여러 작업을 수행한다.
    • 1) 렌더링 : 화면 그리기 (일반적으로 1초에 60프레임, 120프레임 등)
    • 2) 물리 연산 : 충돌 중력 마찰 등 물리 엔진 처리
    • 3) 오브젝트 업데이트 : 게임 내 액터들의 상태 갱신
  • 특정 액터가 '매 프레임마다' 수행할 로직이 있다면, 언리얼 엔진은 그 액터의 Tick(float DeltaTime) 함수를 매 프레임 호출해준다.

 

3-2. Tick 함수 활성화하기

  • Tick() 함수를 사용하려면, 아래와 같이 생성자에서 설정해야 한다.
PrimaryActorTick.bCanEverTick = true;
  • bCanEverTick가 false면 엔진은 성능 최적화를 위해 해당 액터의 Tick을 호출하지 않는다.
  • 불필요한 Tick 호출은 성능에 부담을 줄 수 있으므로, 사용하지 않는다면 false를 명시해주어 최적화 코드 명확성을 높인다.

3-3. DeltaTime

  • Tick(float DeltaTime) 함수에서 DeltaTime은 '직전 프레임부터 현재 프레임까지 걸린 시간(초)'.
    • 60 FPS 환경 : DeltaTime = 1/60초 = 0.0167초
    • 120 FPS 환경 : DeltaTime = 1/120초 = 0.0083초
  • 프레임 레이트가 높을수록 DeltaTime이 작아지고, 낮을수록 DeltaTime이 커진다. 

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

  • 단순히 '매 프레임마다 X 좌표를 1씩 증가' 시키면, FPS가 높을수록 더 빨리 움직여 게임 체감 속도가 달라진다.
  • 이를 방지하려면, DeltaTime을 곱해서 초 단위 기준으로 이동 회전을 계산해야 한다.
  • 이렇게 하면 어느 FPS 환경에서도 동일한 실제 속도를 유지할 수 있다.

 

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

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

헤더 파일
float RotationSpeed;                         
virtual void Tick(float DeltaTime) override; 


// cpp파일

// 생성자에 추가
PrimaryActorTick.bCanEverTick = true;	// Tick함수 활성화
RotationSpeed = 90.0f;                  // 회전속도 (1초에 90도씩 회전)



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::IsNearZero( ) : 부동소수점 비교에서 안전하게 0에 가까운지 확인해주는 함수.
  • AddActorLocalRotation( ) : 액터의 로컬 기준으로 회전을 추가해주는 함수.
    • 만약 월드 좌표 기준으로 회전하고 싶다면 AddActorWorldRotation().