포스트

TIL 2026-04-14

TIL 2026-04-14

2026-04-14 Unreal 5 과제6 — 회전 발판 & 움직이는 장애물

목차


BasePlatformActor — bool로 회전/이동 분기

설계 방식

단일 C++ 베이스 클래스에 bool 변수로 회전/이동 동작을 분기. ARotatingPlatform, AMovingPlatform 자식 클래스에서 기본값만 오버라이드.

핵심 구조

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 회전
if (bShouldRotate)
    AddActorLocalRotation(FRotator(0.f, RotationSpeed * DeltaTime, 0.f));

// 이동 (왕복)
if (bShouldMove)
{
    CurrentOffset += MoveDir * MoveSpeed * DeltaTime;
    if (FMath::Abs(CurrentOffset) >= MaxRange)
    {
        MoveDir *= -1.f;
        CurrentOffset = FMath::Sign(CurrentOffset) * MaxRange;
    }
    // EMoveAxis(X/Y/Z)에 따라 위치 적용
    SetActorLocation(NewLocation);
}

EMoveAxis 열거형

에디터 Details 패널에서 드롭다운으로 이동 축 선택.

1
2
3
4
5
6
7
UENUM(BlueprintType)
enum class EMoveAxis : uint8
{
    X UMETA(DisplayName = "X (앞뒤)"),
    Y UMETA(DisplayName = "Y (좌우)"),
    Z UMETA(DisplayName = "Z (상하)")
};

자식 클래스

1
2
3
4
5
6
7
// ARotatingPlatform 생성자
bShouldRotate = true;
bShouldMove   = false;

// AMovingPlatform 생성자
bShouldRotate = false;
bShouldMove   = true;
클래스역할기본 활성
ABasePlatformActor회전 + 이동 로직 전체 보유둘 다 false
ARotatingPlatform회전 전용bShouldRotate = true
AMovingPlatform이동 전용bShouldMove = true

TimerPlatform — FTimerHandle 도전과제

동작 사이클

발판이 일정 시간 후 사라지고, 일정 시간 후 복구되는 사이클 반복.

1
2
3
4
BeginPlay
  └→ [ActiveDuration 후] DeactivatePlatform (숨김 + 콜리전 제거)
        └→ [InactiveDuration 후] ActivatePlatform (복구)
              └→ [ActiveDuration 후] DeactivatePlatform ... (반복)

핵심 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void ATimerPlatform::DeactivatePlatform()
{
    SetActorHiddenInGame(true);
    SetActorEnableCollision(false);

    // 일회성 타이머 → ActivatePlatform 호출
    GetWorld()->GetTimerManager().SetTimer(
        InactiveTimerHandle, this,
        &ATimerPlatform::ActivatePlatform,
        InactiveDuration, false
    );
}

void ATimerPlatform::ActivatePlatform()
{
    SetActorHiddenInGame(false);
    SetActorEnableCollision(true);

    // 다시 DeactivatePlatform 예약 (사이클 유지)
    GetWorld()->GetTimerManager().SetTimer(
        ActiveTimerHandle, this,
        &ATimerPlatform::DeactivatePlatform,
        ActiveDuration, false
    );
}

SetTimer(..., false) 일회성으로 서로 호출 → 정상 사이클 동작


RandomSpawner — SpawnActor + 랜덤 도전과제

설계

  • BeginPlay: 플레이어 위치 기준으로 초기 발판 N개를 1초 간격 타이머로 순차 스폰
  • Tick: 플레이어가 마지막 발판 800cm 이내 접근 시 추가 배치 재시작

X축 앞 방향 스폰

1
2
3
4
5
6
7
float ForwardDist = FMath::RandRange(MinSpawnDistance, MaxSpawnDistance);
float LateralDist = FMath::RandRange(-MaxSpawnDistance * 0.4f, MaxSpawnDistance * 0.4f);
float Height      = FMath::RandRange(-HeightVariation, HeightVariation);

SpawnLocation.X += ForwardDist;  // 항상 앞으로
SpawnLocation.Y += LateralDist;  // 좌우 분산
SpawnLocation.Z += Height;

랜덤 속성 부여

1
2
3
4
NewPlatform->RotationSpeed = FMath::RandRange(30.f, 150.f);
NewPlatform->MoveSpeed     = FMath::RandRange(100.f, 350.f);
NewPlatform->MaxRange      = FMath::RandRange(150.f, 400.f);
NewPlatform->MoveAxis      = static_cast<EMoveAxis>(FMath::RandRange(0, 1));

캐릭터 스탯 기준 거리 설정

JumpZVelocity=700, MaxWalkSpeed=500 기준으로 최대 점프 수평 거리 ~700cm.

항목
MaxSpawnDistance550cm
SpawnInterval2초

낙사 리스폰 — Character Tick

구현 방식

캐릭터 Tick에서 Z 좌표 체크 → 기준 이하면 시작 위치로 순간이동.

1
2
3
4
5
6
7
8
9
10
void ANBC_AssignmentCharacter::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

    if (GetActorLocation().Z < FallDeathZ)
    {
        SetActorLocation(RespawnLocation);
        GetCharacterMovement()->Velocity = FVector::ZeroVector;
    }
}

UPROPERTY로 에디터 조정

1
2
3
4
5
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Respawn")
float FallDeathZ;        // 기본값 -500.f

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Respawn")
FVector RespawnLocation; // 기본값 (0, 0, 90)

Velocity = FVector::ZeroVector 로 낙하 속도 초기화 → 리스폰 후 튕김 방지

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.