unreal 8기

[6번 과제] 회전발판과 움직이는 장애물

왕건 2026. 4. 9. 21:30


서로 다른 액터 클래스 2개 이상 구현

나는 이렇게 총 세개를 구현 해보았다.

 

USceneComponent* SceneRoot;
UStaticMeshComponent* StaticMeshComp;

각각의 헤더파일에 공통으로 들어가는 코드

 

SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
SetRootComponent(SceneRoot);

StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
StaticMeshComp->SetupAttachment(SceneRoot);

static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/ Script / Engine.StaticMesh'/Game/Resources/Props/Floor_400x400.Floor_400x400'"));
if (MeshAsset.Succeeded())
{
	StaticMeshComp->SetStaticMesh(MeshAsset.Object);
}

static ConstructorHelpers::FObjectFinder<UMaterial> MaterialAsset(TEXT("/Script/Engine.Material'/Game/Resources/Materials/M_Ground_Moss.M_Ground_Moss'"));
if (MaterialAsset.Succeeded())
{
	StaticMeshComp->SetMaterial(0, MaterialAsset.Object);
}

MovingPlatform의 cpp파일인데 위 헤더파일에 선언한 컴포넌트 중 루트 컴포넌트를 설정하고
하위에 StaticMesh컴포넌트를 자식컴포넌트로 설정한다.

 

그리고 StaticMesh와 Material 설정도 해준다.


Tick 함수 기반 동적 Transform 변경

 

회전 기능

void AFloor1::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	
	if (RotationSpeed != 0.0f)
	{
		AddActorLocalRotation(FRotator(0.0f, RotationSpeed * DeltaTime, 0.0f));
	}
}

Floor1의 Tick함수인데 이름을 잘못 설정했지만 그냥 하였다.

RotationSpeed가 0이 아닐때에만 돌게 배운대로 안전장치를 해놓았다. 

 

// Called every frame
void AStar::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	if (RotationSpeed != 0.0f)
	{
		AddActorLocalRotation(FRotator(0.0f, RotationSpeed * DeltaTime, 0.0f));
	}
}

 

이건 Star의 Tick함수인데 위와 동일하다.


이동 기능

void AMovingPlatform::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	AddActorLocalOffset(FVector(0.0f, MoveSpeed * DeltaTime, 0.0f));

	DistanceMoved = FVector::Dist(StartLocation, GetActorLocation());

	if (DistanceMoved >= MaxRange)
	{
		StartLocation = GetActorLocation();
		MoveSpeed = -MoveSpeed;

		DistanceMoved = FVector::Dist(StartLocation, GetActorLocation());
		if (DistanceMoved >= MaxRange)
		{
			MoveSpeed = MoveSpeed;
		}
	}

 

이건 MovingPlatform의 Tick함수인데

void AMovingPlatform::BeginPlay()
{
	Super::BeginPlay();
	StartLocation = GetActorLocation();
}

 

BeginPlay에서 액터의 현재 위치를 StartLocation으로 설정하여 기준을 잡고

 

AddActorLocalOffset(FVector(0.0f, MoveSpeed * DeltaTime, 0.0f));

 

MoveSpeed를 DeltaTime에 곱한 값으로 이동시키고 (MoveSpeed 증가 = 액터의 이동속도 증가)

DistanceMoved (이동거리)를 FVector::Dist(StartLocation, GetActorLocation());로 구해준다.

if (DistanceMoved >= MaxRange)
{
	StartLocation = GetActorLocation();
	MoveSpeed = -MoveSpeed;

	DistanceMoved = FVector::Dist(StartLocation, GetActorLocation());
	if (DistanceMoved >= MaxRange)
	{
		MoveSpeed = MoveSpeed;
	}
}

 

만약 이동거리가 설정해놓은 MaxRange보다 커지거나 같아질경우 MoveSpeed에 음수를 대입하여 반대로 이동하게 한뒤
다시 거리를 계산하여 MaxRange보다 커지거나 같아지면 다시 양수를 대입하여 또 반대로 이동하게 하였다.


프레임 독립성

AddActorLocalRotation(FRotator(0.0f, RotationSpeed * DeltaTime, 0.0f));
AddActorLocalOffset(FVector(0.0f, MoveSpeed * DeltaTime, 0.0f));

 

다 델타타임을 사용하여 계산했으므로 움직임 보장


리플렉션 적용

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="MovingPlatform|Components")
float MoveSpeed;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MovingPlatform|Components")
float MaxRange;
float DistanceMoved;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Floor1|Components")
float RotationSpeed;

 

주요 변수들을 리플렉션을 이용해 에디터에서 독립적으로 변경가능하게 하였다.


https://youtu.be/fz_UbRPBC9M

 

시연 영상