💭회고
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));
}
}
🟣오늘의 옵시디언 현황
'Dev. > UE 언리얼 엔진' 카테고리의 다른 글
[TIL_250129] 회전 발판, 움직이는 장애물, 비물질 발판 구현하기 (2) - &충돌, 히트 감지 (1) | 2025.01.29 |
---|---|
[TIL_250128] 회전 발판, 움직이는 장애물, 비물질(?) 발판 구현하기 (0) | 2025.01.28 |
[TIL_250127] [스파르타코딩클럽 후기] C++와 Unreal Engine으로 3D 게임 개발 - 리플렉션 시스템 이해하기! (0) | 2025.01.27 |
[TIL_250124] Tick 함수로 Actor의 Transform 조정하기 (2) (0) | 2025.01.24 |
[TIL_250122] 로그 출력, Actor's Lifecycle, Transform (0) | 2025.01.22 |