Unreal

[과제 5] Unreal Engine 활용 프로그램

(ꐦ •᷄ࡇ•᷅) 2025. 1. 7. 16:03

개발 프로세스 가이드

1단계 : 액터 생성하기

  • 언리얼 엔진에서 새로운 엑터를 생성한다.
  • 언리얼 엔진 동작시 엑터가 스폰(spawn)될 수 있도록 추가한다.

2단계 : 로직 설계하기

  • 엑터가 스폰(spawn)될 때 수행할 동작을 설계한다.
  • 이번 강의에서는 엑터 자체 동작이 아닌, 액터가 스폰되는 시점에 로그가 출력될수 있도록 한다.

3단계 : 구현하기

  • UE_LOG를 활용하여 설계한 내용을 바탕으로 로그를 출력 할 수 있도록 구현한다.
  • 엔진에서 결과를 테스트하고 필요시 수정한다.

필수 기능 가이드

새로운 엑터를 생성하고 엑터가 spawn 되는 시점에 동작되도록 아래 요구사항대로 동작하도록 코드를 구현한다.

시작점(0,0) 있는 게임 캐릭터가 랜덤하게 10회 이동한다. 각 스텝에서 거쳐간 좌표를 모두 출력하는게 목적이다.

세부 요구사항은 아래와 같다.

  • 시작점은 (0,0)이고 한번 이동시 x좌표와 y좌표 모두 2이상 이동할 수 없다. 예를 들면 아래와 같다.
    • (0,0) 에서 (1,2)은 이동할수 없다. y좌표가 2이상 이동했기 때문이다.
    • (0,0)에서 (1,1)은 이동할 수 있다. x좌표 y좌표 모두 2미만 이동했기 때문이다.
  • 이동은 입력을 받는게 아니고 10회 모두 랜덤으로 움직인다.
  • 매번 이동시 현재 좌표를 출력할 수 있어야 한다.
  • 로그 출력은 UE_LOG를 활용한다.
  • step 함수는 x좌표 y좌표 각각 이동할 거리이다.
    • 예를들어서 현재 좌표가(x1,y1)이라면 다음 좌표는 (x1+step 함수의 리턴값,y1 + step함수의 리턴 값) 이다.
    • step함수는 0혹은 1을 랜덤으로 반환한다.
  • move함수는 (0,0)부터 10회 움직이면서 좌표를 출력한다. 이동시 step 함수가 활용된다.

참고용 클래스 다이어그램

도전 기능 가이드

필수 기능 구현을 완료한 후 아래 기능을 추가한다.

  • 10회 이동시 각 스텝마다 이전 좌표기준 이동 거리를 계산해서 출력한다. 이동 거리는 아래와 같이 계산한다.

  • 10회 이동시 각 스텝마다, 50% 확률로 랜덤하게 이벤트가 발생한다. 각 스텝마다 이벤트 발생여부를 출력한다.
  • 10회 이동후에는 총 이동거리와 총 이벤트 발생횟수를 출력한다.

참고용 클래스 다이어그램

1. 액터 생성하기

액터가 스폰될 시 수행할 동작을 설계하는 것이기 때문에 BeginPlay()를 호출할 액터를 하나 만든다. 

Tools > New C++ Class로 새로운 액터를 만들어 주었다. 이름은 GameLogger로 하였다.

 

생성된 액터의 모습

이제 이 액터의 BeginPlay()에서 동작을 호출할 것이니 C++ 클래스를 수정해 준다.

 

2. 기능 구현하기

  • 제한 사항에 맞춰서 랜덤으로 10회 이동하고 그 좌표를 매번 출력하게 구현한다. 
  • 이동할 때마다 이동한 거리를 출력한다. 
  • 스텝마다 50 퍼센트의 확률로 이벤트를 호출한다.
  • 마지막에 총 이동 거리와 총 이벤트 호출 횟수를 출력한다. 

2-1. 헤더 파일에 함수 추가

UCLASS()
class HELLO_API AGameLogger : public AActor
{
	GENERATED_BODY()
private:
	FVector2D position;
	int32 evCnt;
	float totDist;

public:
	const int32_t MIN_STEP = 0;
	const int32_t MAX_STEP = 1;
	const int32_t STEP_COUNT = 10;
	
public:	
	// Sets default values for this actor's properties
	AGameLogger();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;


public:
	void Move();
	int32_t Step();

	float Distance(FVector2D first, FVector2D second);
	void CreateEvent();
};

 

클래스 다이어그램을 참고하여 프라이빗 변수와 헤더 파일 마지막 부분에 함수를 만들어 주었다.

그리고 STEP_COUNT 등 하드코딩될 법한 상수는 헤더에서 const로 처리해 주었다.

 

여기서 잠깐! int32_t는 무엇일까?

더보기

int32_t는 32비트 정수형 자료형으로, 부호가 있는 정수를 나타낸다. 이는 stdint.h (또는 C++에서는 cstdint) 헤더 파일에 정의된 표준 자료형이다.

주요 특징:

  1. 크기: int32_t는 32비트 크기, 즉 4바이트를 차지한다.
  2. 범위:
    • int32_t는 부호 있는 정수이기 때문에, 표현할 수 있는 값의 범위는 -2,147,483,648부터 2,147,483,647까지이다.
    • 범위: -2^31 ~ 2^31 - 1

언리얼 엔진에서의 사용

언리얼 엔진은 다양한 플랫폼과 아키텍처에서 동작하는 게임 엔진이므로, 플랫폼 독립적인 자료형을 사용하는 것이 중요하다. int32_t는 다양한 컴파일러와 플랫폼에서 동일한 크기와 범위를 보장하기 때문에, 크기나 범위가 중요한 곳에서 사용된다.

언리얼 엔진은 기본적으로 int32 같은 자료형을 제공하지만, int32_t는 표준 C++ 자료형으로, 호환성을 위해 사용될 수 있다.

2-2. GameLogger.cpp 구현

// Fill out your copyright notice in the Description page of Project Settings.


#include "GameLogger.h"

// Sets default values
AGameLogger::AGameLogger()
{
 	// 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;
}

// Called when the game starts or when spawned
void AGameLogger::BeginPlay()
{
	Super::BeginPlay();

	// Count만큼 좌표 랜덤 이동
	for (int i = 0; i < STEP_COUNT; i++)
		Move();
	

	// 총 이동한 거리와 이벤트 발생 수 출력
	UE_LOG(LogTemp, Warning, TEXT("Total Distance: %f \t Total Event Count: %d"), totDist, evCnt);
}

// Called every frame
void AGameLogger::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

// 랜덤한 좌표를 반환한다.
void AGameLogger::Move()
{
	// 랜덤 이벤트
	CreateEvent();

	int32_t nx = position.X + Step();
	int32_t ny = position.Y + Step();

	FVector2D curPos = position;
	FVector2D nextPos = FVector2D(nx, ny);

	// Distance, Position
	float curDist = Distance(nextPos, curPos);
	position = nextPos;

	// 거리, 좌표 출력
	UE_LOG(LogTemp, Warning, TEXT("Distance: %f \t Cur position: (%d, %d)"), curDist, nx, ny);
	// 개행
	UE_LOG(LogTemp, Warning, TEXT("----------------------------------------"), curDist, nx, ny);
}


// 0, 1을 랜덤으로 반환한다.
int32_t AGameLogger::Step()
{
	int32_t step = FMath::RandRange(MIN_STEP, MAX_STEP);

	return step;
}

float AGameLogger::Distance(FVector2D first, FVector2D second)
{
	float xDist = second.X - first.X;
	float yDist = second.Y - first.Y;

	// dist구하고 total dist에 현재 dist 더하기 
	float dist = FMath::Sqrt(xDist * xDist + yDist * yDist);
	totDist += dist;

	return dist;
}

void AGameLogger::CreateEvent()
{
	int32_t flag = FMath::RandRange(0, 1);

	// 이벤트 발생  
	if (flag == 1)
	{
		// 이벤트 출력
		UE_LOG(LogTemp, Display, TEXT("Event!!!!!!!!!!!!!!"))
		evCnt++;
	}
}

 

필수와 도전 요구 사항을 모두 충족한 구현이다.

 

처음엔 Step 함수 안에 이벤트 발생 함수를 넣었는데, 총 이벤트 발생 수가 최대 걸음 횟수 10을 넘는 문제가 있었다. 문제는 Step함수가 걸음 하나를 구현할 때 2번 호출되는 것이었다. 그래서 Move 함수 안에 이벤트를 발생시키는 함수를 넣었다. 

 

2-3. 결과