C++와 Unreal Engine으로 3D 게임 개발 과제 6
[TIL] 2025-01-15 | UE 회전 발판과 움직이는 장애물
C++와 Unreal Engine으로 3D 게임 개발 과제 61. WHY이번 과제는 언리얼 C++과 엔진 기능 (Actor, Tick, 리플렉션 시스템 등)을 활용해 간단한 퍼즐용 오브젝트들을 준비하는 과제입니다.회전 발판, 이동 플
zzageuli.tistory.com
지난번에 했던 과제에 어제 배운 타이머를 추가해보려고 한다.

피라미드 입구에 충돌을 감지하고 2초 뒤 문이 열리도록 하고자 한다.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Door.generated.h"
class UBoxComponent;
UCLASS()
class NBC_UE_P6_API ADoor : public AActor
{
GENERATED_BODY()
public:
ADoor();
virtual void Tick(float DeltaTime) override;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Comp")
USceneComponent* Scene;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Comp")
UBoxComponent* Box;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Comp")
UStaticMeshComponent* MeshComp;
UFUNCTION()
void OnItemOverlap(UPrimitiveComponent* OverlappedComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex,
bool bFromSweep,
const FHitResult& SweepResult);
void MovingDoor();
FTimerHandle TimerHandle;
bool IsMoving;
};
#include "Door.h"
#include "Components/BoxComponent.h"
ADoor::ADoor()
{
PrimaryActorTick.bCanEverTick = true;
Scene = CreateDefaultSubobject<USceneComponent>(TEXT("Scene"));
SetRootComponent(Scene);
Box = CreateDefaultSubobject<UBoxComponent>(TEXT("Collision"));
Box->SetCollisionProfileName(TEXT("OverlapAllDynamic"));
Box->SetupAttachment(Scene);
MeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
MeshComp->SetupAttachment(Scene);
Box->OnComponentBeginOverlap.AddDynamic(this, &ADoor::OnItemOverlap);
IsMoving = false;
}
void ADoor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (IsMoving)
{
AddActorLocalOffset(FVector(0.f, 0.f, 200.f * DeltaTime));
}
}
void ADoor::OnItemOverlap(
UPrimitiveComponent* OverlappedComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex,
bool bFromSweep,
const FHitResult& SweepResult)
{
if (OtherActor) //충돌 체크
{
GetWorld()->GetTimerManager().SetTimer(
TimerHandle, // FTimerHandle
this, // this 포인터
&ADoor::MovingDoor, // 호출할 함수
2.f, // 지연 시간 (초)
false // 반복 여부
);
}
}
void ADoor::MovingDoor()
{
IsMoving = true;
}
일단 이동 범위는 제한하지 않고 테스트해봤다.

위로 가도록 했더니 위에 숨길 공간이 없었다.
아래로 이동하도록 변경하고 일정 거리만큼 이동하면 이동을 멈춰야겠다.
#include "Door.h"
#include "Components/BoxComponent.h"
ADoor::ADoor()
{
PrimaryActorTick.bCanEverTick = true;
Scene = CreateDefaultSubobject<USceneComponent>(TEXT("Scene"));
SetRootComponent(Scene);
Box = CreateDefaultSubobject<UBoxComponent>(TEXT("Collision"));
Box->SetCollisionProfileName(TEXT("OverlapAllDynamic"));
Box->SetupAttachment(Scene);
MeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
MeshComp->SetupAttachment(Scene);
Box->OnComponentBeginOverlap.AddDynamic(this, &ADoor::OnItemOverlap);
IsMoving = false;
}
void ADoor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (IsMoving)
{
AddActorLocalOffset(FVector(0.f, 0.f, -200.f * DeltaTime));
if (FVector::Dist(GetActorLocation(), StartLocation) > 1000.f)
{
Destroy();
}
}
}
void ADoor::OnItemOverlap(
UPrimitiveComponent* OverlappedComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex,
bool bFromSweep,
const FHitResult& SweepResult)
{
if (OtherActor) //충돌 체크
{
GetWorld()->GetTimerManager().SetTimer(
TimerHandle, // FTimerHandle
this, // this 포인터
&ADoor::MovingDoor, // 호출할 함수
2.f, // 지연 시간 (초)
false // 반복 여부
);
}
}
void ADoor::MovingDoor()
{
StartLocation = GetActorLocation();
IsMoving = true;
}
이동을 멈추면 매번 Tick이 불필요하게 연산될 거 같아 그냥 Destroy()를 호출했다.
처음에 생성자에서 시작위치를 Get했더니 충돌되자마자 파괴되는 현상이 있었다.
알고보니 생성자에서는 아직 월드에 배치되지않아 위치가 (0,0,0) 이라고 한다.
그래서 IsMoving을 true로 바꿔줄 때 위치값을 가져와서 이동 거리를 계산해줬다.

'내배캠Unreal_TIL > UE' 카테고리의 다른 글
| [TIL] 2026-01-22 | UE GameplayTags (0) | 2026.01.22 |
|---|---|
| [TIL] 2026-01-21 | UE 게임 기초 시스템 구현 (0) | 2026.01.21 |
| [TIL] 2026-01-19 | UE 아이템 시스템 구현하기 (2), Timer, SpawnActor (0) | 2026.01.19 |
| [TIL] 2026-01-16 | UE 아이템 시스템 구현하기 (1), 아이템 인터페이스 (1) | 2026.01.16 |
| [TIL] 2026-01-16 | UE 애니메이션 리타겟팅 (0) | 2026.01.16 |