오늘은 언리얼 엔진에서 AActor를 상속받아 랜덤 이동(Random Walk) 을 구현했다.
Step()은 X/Y축 이동을 결정하고, ShouldTriggerEvent()는 50% 확률로 이벤트를 발생시킨다.
10번 이동 후 총 이동 거리와 이벤트 발생 횟수를 로그로 확인할 수 있다. 🚀
AActor 클래스 상속과 기본 구조 학습 BeginPlay, Tick 오버라이드 구조 이해 #pragma once // 헤더 파일의 중복 포함을 방지
#include "CoreMinimal.h" // 언리얼 엔진의 핵심 기능을 제공하는 헤더
#include "GameFramework/Actor.h" // AActor 기본 클래스 정의
#include "MyActor.generated.h" // 리플렉션 시스템용 자동 생성 코드 포함
// 언리얼 리플렉션 시스템에 등록될 AMyActor 클래스 선언
UCLASS()
class HOMEWORK5_API AMyActor : public AActor
{
GENERATED_BODY() // UE 리플렉션 및 직렬화를 위한 매크로
public:
AMyActor(); // 기본 생성자
protected:
virtual void BeginPlay() override; // 액터가 생성되어 게임이 시작될 때 한 번 실행
public:
virtual void Tick(float DeltaTime) override; // 매 프레임마다 호출되는 업데이트 함수
private:
int32 Step(); // 0 또는 1을 무작위 반환해 X/Y축 이동에 사용
bool ShouldTriggerEvent(); // 50% 확률로 true 반환 → 이벤트 발생 여부 결정
void Move(); // (0,0)에서 시작해 10번 이동하며 이동 결과와 이벤트 여부를 로그로 출력
};
#include "MyActor.h"
#include "Math/UnrealMathUtility.h"
#include "Engine/Engine.h"
// 기본 생성자
AMyActor::AMyActor()
{
PrimaryActorTick.bCanEverTick = true; // Tick 함수가 매 프레임마다 호출되도록 활성화
}
// 게임 시작 시 실행
void AMyActor::BeginPlay()
{
Super::BeginPlay(); // 부모 클래스의 BeginPlay 동작 수행
Move(); // 게임 시작 시 이동 시뮬레이션 실행
}
// 매 프레임마다 호출
void AMyActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime); // 부모 클래스의 Tick 동작 실행 (매 프레임마다 호출)
}
// X/Y축 이동 방향 결정 (0 또는 1)
int32 AMyActor::Step()
{
return FMath::RandRange(0, 1); // 0 또는 1 중 하나를 무작위 반환 (X/Y축 이동에 사용)
}
// 이벤트 발생 여부 (50% 확률)
bool AMyActor::ShouldTriggerEvent()
{
return FMath::RandBool(); // 50% 확률로 true 또는 false 반환 (이벤트 발생 여부 결정)
}
// 이동 시뮬레이션
void AMyActor::Move()
{
FVector2D CurrentPosition(0, 0); // 현재 위치를 (0,0)으로 초기화
FVector2D PreviousPosition = CurrentPosition; // 직전 위치 저장용 변수
float TotalDistance = 0.0f; // 누적 이동 거리
int32 EventCount = 0; // 이벤트 발생 횟수
for (int32 i = 0; i < 10; ++i) // 총 10번 이동 반복
{
PreviousPosition = CurrentPosition; // 이동 전 위치를 보관
// 무작위 이동
int32 dx = Step(); // X축 이동량 (0 또는 1 무작위)
int32 dy = Step(); // Y축 이동량 (0 또는 1 무작위)
CurrentPosition.X += dx;
CurrentPosition.Y += dy;
// 이동 거리 계산
float StepDistance = FVector2D::Distance(CurrentPosition, PreviousPosition); // 현재 위치와 이전 위치 사이 거리 계산
TotalDistance += StepDistance; // 총 이동 거리 누적
// 이벤트 발생 여부
bool bEventTriggered = ShouldTriggerEvent(); // 50% 확률로 이벤트 발생 여부 결정
if (bEventTriggered)
{
EventCount++; // 이벤트가 발생하면 카운트 증가
}
// 이동 로그 출력
UE_LOG(LogTemp, Log, TEXT("Step %d:"), i + 1); // 현재 스텝 번호 출력
UE_LOG(LogTemp, Log, TEXT(" From (%d, %d) to (%d, %d)"),
(int32)PreviousPosition.X, (int32)PreviousPosition.Y,
(int32)CurrentPosition.X, (int32)CurrentPosition.Y); // 이동 전후 좌표 출력
UE_LOG(LogTemp, Log, TEXT(" Step Distance: %.2f"), StepDistance); // 이번 이동 거리 출력
UE_LOG(LogTemp, Log, TEXT(" Event Triggered: %s"), bEventTriggered ? TEXT("Yes") : TEXT("No")); // 이벤트 발생 여부 출력
}
// 최종 결과 출력
UE_LOG(LogTemp, Warning, TEXT("=== Movement Summary ===")); // 이동 과정 요약 출력
UE_LOG(LogTemp, Warning, TEXT("Total Distance: %.2f"), TotalDistance); // 전체 이동 거리 출력
UE_LOG(LogTemp, Warning, TEXT("Total Events Triggered: %d"), EventCount); // 전체 이벤트 발생 횟수 출력
}
Tick() 안에서 Move()를 계속 호출해서, 매 프레임마다 무한히 이동 로그가 쌓였다 🐌 FVector2D 대신 FVector를 써버려서 거리 계산은 3D로 맞는데, 좌표는 2D 이동이라 결과가 헷갈리게 나왔다 🤯 FMath::RandRange(0,1)을 잘못 이해해서 0~1 사이의 실수가 나오는 것으로 착각했다. 🔍 | 개념 | 설명 | 비고 |
|---|---|---|
| BeginPlay | 액터가 시작될 때 한 번 실행 | 시작 동작 처리 |
| Tick | 매 프레임마다 호출되는 함수 | 성능 주의 |
| FMath::RandRange | 지정 범위 내 난수 반환 (정수/실수 지원) | 여기선 0~1 |
| FMath::RandBool | true/false 무작위 반환 (50% 확률) | 이벤트 발생 |
| UE_LOG | 로그 출력 매크로, Log/Warning/Error 구분 가능 | 디버깅 활용 |