기본 기능
- 서로 다른 Actor 클래스 2개 이상 구현
- [ ] C++ Actor 클래스 최소 2개 생성
- 각 StaticMeshComponent 포함 맵에 배치 가능한 형태여야합니다.
- 두 클래스는 서로 다른 동작 로직(회전용 / 이동용 등) 수행해야합니다.
- 회전 기능 (Rotating Actor)
- ick(float DeltaTime) 에서 AddActorLocalRotation()로 매 프레임 회전 적용
- Tick(float DeltaTime)에서 위치를 변경하여 왕복 이동 구현
- StartLocation(시작 위치) 저장/기준점으로 사용
- MoveSpeed(이동 속도) 적용
- MaxRange(왕복 범위) 기준으로 이동 제한
- 이동/회전 시 반드시 DeltaTime 을 활용
- 하드웨어 성능에 관계 없이 일정한 움직임을 보장해야합니다.
- 회전하는 톱니바퀴, 엘리베이터 등으로 자유롭게 확장 가능합니다.
- 오브젝트 배치 및 테스트
- 레벨에 제작한 회전 발판과 이동 플랫폼을 여러 개 배치
- 각각 다른 속도, 이동범위, 회전값 적용
- 플레이 모드에서 오브젝트가 의도대로 움직이는지 확인
- 속도 변경이 실시간 반영되는지 확인

도전 기능
- 타이머 시스템 활용
- FTimerHandle과 GetWorld()->GetTimerManager().SetTimer(...)를 사용해 특정 시간 후 또는 주기적으로 함수를 호출
- 매 프레임 호출(Tick)보다 효율적인 퍼포먼스를 제공
- 일정 시간 후 발판이 사라지거나, 주기적으로 다른 위치로 이동하는 로직 추가
- 랜덤 퍼즐 생성
- 동적 스폰
- 게임 시작 시 SpawnActor를 통해 회전 발판/이동 플랫폼을 임의 좌표에 여러 개 배치
- 참고 : 언리얼 공식 문서 SpawnActor
- 랜덤 스테이지의 기초 개념을 체험할 수 있습니다.
- 회전/이동 속도, 이동 범위, 각도 등을 FMath::RandRange로 생성하여 매번 다른 퍼즐 코스를 구성
- 동적 스폰

액터 사이즈 변경하기
플랫폼으로 사용하기 위해 Cube를 납작하게 만들어 사용하려고 한다.
그런데 SetActorScale3D()를 적용하면 콘텐츠 드로어에서는 원본 스태틱메시 상태가 그대로 보여 뷰포트에 배치하기 전까지는 납작한지 아닌지 알 수 없다. 그래서 콘텐츠 드로어에서도 납작하게 보이도록 수정해주었다.

AMovingPlatform::AMovingPlatform()
{
SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
SetRootComponent(SceneRoot);
StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
StaticMeshComp->SetupAttachment(SceneRoot);
static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/Game/Resources/Shapes/Shape_Cube.Shape_Cube"));
if (MeshAsset.Succeeded())
{
StaticMeshComp->SetStaticMesh(MeshAsset.Object);
// SetActorScale3D(FVector(1.0f, 1.0f, 0.2f)); 이거 말고 SetRelativeScale3D로 아래처럼 바꿔줘야 CDO가 바뀌면서 콘텐츠 드로어 썸네일에 적용된다!
StaticMeshComp->SetRelativeScale3D(FVector(1.0f, 1.0f, 0.2f));
}
static ConstructorHelpers::FObjectFinder<UMaterialInterface> MaterialAsset(TEXT("/Game/Resources/Materials/M_Rock_Basalt.M_Rock_Basalt"));
if (MaterialAsset.Succeeded())
{
StaticMeshComp->SetMaterial(0, MaterialAsset.Object);
}
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
MoveSpeed = 100.0f;
}
StaticMeshComp->SetRelativeScale3D(FVector(1.0f, 1.0f, 0.2f)); 처럼 스태틱 메시 자체를 SetRelativeScale3D로 지정해줘야만 썸네일까지 바뀌니 참고하도록 하자.
소스 파일명 변경
기존 클래스 파일명인 Flatform_A와 _B를 오타 없고 직관적인 이름으로 변경하고자 VS에서 파일명을 각각 RotatingPlatform, MovingPlatform으로 바꿔주었다.
이렇게 파일명만 바꿔주면 언리얼에서 배치해놓은 액터들에 대해 경로를 찾지 못한다는 에러가 나므로, 기존에 있던 액터들을 없애거나 리다이렉트로 연결해주어야한다. 둘 중 하나만 하면 되는데, 웬만하면 리다이렉트 코드를 추가하자.
1. 기존 액터 삭제
기존 액터는 umap파일에 남아있기 때문에 뷰포트에 남아 오류 메시지를 일으킨다. 하지만 아웃라이너에는 아예 보이지 않는다. 그래도 삭제하는 방법이 있긴 하다.
- 프로젝트가 초기라서 액터를 삭제해도 된다면, Ctrl+A를 눌러 아웃라이너의 모든 액터를 선택한다. 아웃라이너의 액터 목록에는 보이지 않아도, 전체 선택을 하면 선택이 된 것이다.
- 아웃라이너에서 현재 유효한 액터는 Ctrl+클릭으로 선택 해제 해준다.
- Delete를 누른다.
- 에디터를 재시작하여 확인한다.
2. DefaultEngine.ini 파일에 리다이렉트 코드 추가하기

[CoreRedirects]
+ClassRedirects=(OldName="Flatform_A", NewName="RotatingPlatform")
+ClassRedirects=(OldName="Flatform_B", NewName="MovingPlatform")
이렇게 +ClassRedirects=(OldName="기존 클래스명", NewName="새 클래스명")을 입력하면 언리얼에서 읽어들여 리다이렉트한다. 한 번 추가하고 레벨 전체 저장하면 다음부터는 삭제해도 된다고 한다. 정리해주자.
굉장히 번거로우니 애초에 클래스명을 잘 짓도록 하자.
'게임 개발 > 학습 일지' 카테고리의 다른 글
| 언리얼 C++ - Character 클래스를 이용한 캐릭터 구현하기 (0) | 2026.04.15 |
|---|---|
| TA 코스 2주차 과제 - 마법 구체 만들기 (0) | 2026.04.15 |
| TA 코스 2주차 정리 (0) | 2026.04.13 |
| TA 코스 1주차 과제 - AI로 3D 모델링 생성 후 언리얼에 적용하기 (0) | 2026.04.13 |
| 언리얼 C++ - 리플렉션 시스템 활용 (0) | 2026.04.12 |