[Day20] Random Walk Simulation

베리투스·2025년 9월 1일

TIL: Today I Learned

목록 보기
28/93

오늘은 언리얼 엔진에서 AActor를 상속받아 랜덤 이동(Random Walk) 을 구현했다.
Step()은 X/Y축 이동을 결정하고, ShouldTriggerEvent()는 50% 확률로 이벤트를 발생시킨다.
10번 이동 후 총 이동 거리와 이벤트 발생 횟수를 로그로 확인할 수 있다. 🚀


📌 목표

  • 언리얼 엔진에서 AActor 클래스 상속과 기본 구조 학습
  • BeginPlay, Tick 오버라이드 구조 이해
  • 난수 기반 이동과 이벤트 발생 로직 구현
  • 로그 출력으로 결과 확인

💻 코드

MyActor.h

#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번 이동하며 이동 결과와 이벤트 여부를 로그로 출력
};

📂 MyActor.cpp

#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::RandBooltrue/false 무작위 반환 (50% 확률)이벤트 발생
UE_LOG로그 출력 매크로, Log/Warning/Error 구분 가능디버깅 활용
profile
Shin Ji Yong // Unreal Engine 5 공부중입니다~

0개의 댓글