Dev./UE 언리얼 엔진

[TIL_250123] Tick 함수로 Actor의 Transform 조정하기

raindrovvv 2025. 1. 23. 23:16

💭회고

Transform, 그리고 Tick 함수 안에 Transform 조절을 통해 액터의 움직임을 만들어내는 것을 배웠다.
이제 움직임이 제대로 눈에 보이게 되니, 더 재밌어지는 것 같다.

금일부터 팀 프로젝트에 대한 내용을 정리해보기 시작했다. 역시 나는 이런 게임 컨셉 기획, 시나리오, 디자인 할 때가 제일 재밌고 잘 맞는듯 하다. 이걸 구현하는 것은 내일의 나, 그리고 그 다음 날의 내가 알아서 잘 하겠지...

🗺️마인드맵

📒학습 내용

트랜스폼의 코드 기본 형태

void AItem::BeginPlay()  
{  
    Super::BeginPlay();  
    SetActorLocation(FVector(200, 200, 200)); // 위치  
    SetActorRotation(FRotator(45, 90, 45)); // Pitch(Y축), Yaw(Z축), Roll(X축) (XYZ가 아님)  
    SetActorScale3D(FVector(2, 5, 3));  
}
- 언리얼 엔진에서 `FVector`와 `FRotator`의 구성 요소가 기본적으로 float 타입으로 취급되기 때문에, 소수점이 없는 정수 값을 사용해도 문제가 없다.
- SetActorRotation(FRotator(45, 90, 45)); // Pitch(Y축), Yaw(Z축), Roll(X축) (X,Y,Z가 아님)

- SetActorScale3D(FVector(2, 2, 2));➡️ `SetActorScale3D(FVector(2)); ` : 이렇게 하면 전체가 2배 스케일이 된다.

트랜스폼 전체를 바꾸기

`FTransform NewTransform(NewRotation, NewLocation, NewScale);`
- 각도, 위치, 스케일 순이다. (아래 참고)
- FTransform이라는 구조체 형태로 한꺼번에 관리할 수 도 있다.

void AItem::BeginPlay()  
{  
    Super::BeginPlay();  
    SetActorLocation(FVector(0, 0, 0));
    SetActorRotation(FRotator(0, 0, 0));
    SetActorScale3D(FVector(0, 0, 0));
    
    FVector const NewLocation(200, 300, 200);  
    FRotator const NewRotation(0.0, 0.0, 0.0);  
    FVector const NewScale(5);  
  
    FTransform NewTransform(NewRotation, NewLocation, NewScale);  
    SetActorTransform(NewTransform);  
    
}

`Tick()`으로 액터 회전시키기

`AddActorLocalRotation(FRotator(0, 0, 0));`
- 자전의 형태는 로컬이 적합하다.

 

1) 프레임에 대한 이해

> Tick함수에서 무언가를 구현할 때는 컴퓨터 성능 차이에 따른 프레임을 염두해 두어야 한다.
> 만약 고성능 컴퓨터에서는 프레임이 120이 나오고, 저성능 컴퓨터에서는 프레임이 60이 나온다면? → 게임이 설계한대로 구현되지 않는다는 것이다.
> 그래서 이를 동일하게 맞춰야 한다.
> ➡️ DeltaTime이 필요하다!

 

2) 방어 코드

0. Tick은 Tick 함수를 켜야만 함수가 동작한다.
   `PrimaryActorTick.bCanEverTick = true;` (생성자에 구현해준다.)
   - Tick함수를 ==사용하지 않을 때는 위 함수를 false로 처리==해놓는 것이 맞다.

1. Tick함수는 계속 해서 동작하기 때문에 조건문을 통해 처리해줘야 한다.

2. 부동소수점은 계산 상의 오차가 존재할 수 있기에 이를 방지하는 코드가 있다.
`if (RotationSpeed != 0)`
⬇️
`FMath::IsNearlyZero` 
- 부동소수점 비교에서 안전하게 0에 가까운지 확인해주는 함수
⬇️
`if (!FMath::IsNearlyZero(RotationSpeed))`
- RotationSpeed가 0에 가깝지 않을 경우 함수 기능이 동작한다.
- 0에 가까울 경우 함수 기능이 동작하지 않는다.
#include "Item.h"  
  
DEFINE_LOG_CATEGORY(LogTeam);  
  
AItem::AItem()  
{  
    RotationSpeed = 900.0f;  //헤더에다가 선언해주고, 소스에서 초기화
    PrimaryActorTick.bCanEverTick = true;  
    SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot")); // 컴포넌트를 생성  
    SetRootComponent(SceneRoot); // SceneRoot 루트 컴포넌트로 설정  
  
    StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh")); // 스태틱 메쉬 생성  
    StaticMesh->SetupAttachment(SceneRoot); // StaticMesh를 SceneRoot에 연결
  
    // StaticMesh 설정  
    static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/Game/Resources/Props/SM_Star_B.SM_Star_B"));  
    if (MeshAsset.Succeeded())  
    {       StaticMesh->SetStaticMesh(MeshAsset.Object);  
    }    // Material 설정  
    static ConstructorHelpers::FObjectFinder<UMaterialInstance> MaterialAsset(TEXT("/Game/Resources/Materials/M_Mango.M_Mango"));
    
void AItem::BeginPlay()  
{  
    Super::BeginPlay();  
    SetActorLocation(FVector(300, 0, 200)); 
    SetActorRotation(FRotator(0, 0, 0));
    SetActorScale3D(FVector(3.5));  
}  
  
void AItem::Tick(float DeltaTime)  
{  
    Super::Tick(DeltaTime);  
  
    if (!FMath::IsNearlyZero((RotationSpeed)))  
    {       AddActorLocalRotation(FRotator(0.f,RotationSpeed * DeltaTime,0.f));      
    }  
}

 

 

응용 1

void AItem::Tick(float DeltaTime)  
{  
    Super::Tick(DeltaTime);  
  
    if (!FMath::IsNearlyZero((RotationSpeed)))  
    {       AddActorLocalRotation(FRotator(RotationSpeed * DeltaTime,RotationSpeed * DeltaTime,RotationSpeed * DeltaTime));      
    }  
}

 

 

 

🟣오늘의 옵시디언 현황