내일배움캠프-언리얼

[내일배움캠프 - 언리얼] DAY 21 - Unreal Engine C++ 활용 프로그램 제작

이시보 2025. 12. 26. 22:08

목표

필수 기능

  • 시작점은 (0, 50, 0) 에서 시작합니다.
  • 생성한 Actor C++ → Blueprint로 상속한 다음 Blueprint에서 StaticMesh추가 후 Cube로 지정
  1. Turn, Move 함수를 만들고 함수를 호출하여 10회 랜덤으로 회전 및 이동 합니다
  2. 매번 이동시 현재 좌표를 출력 합니다.
  3. 로그 출력은 AddOnScreenDebugMessage를 활용합니다.

도전 기능

  • 필수 기능 구현을 완료한 후 아래 기능을 추가 힙니다.
  1. 시작점은 (0, 50, 0)이고 한번 이동시 현재 좌표 및 이동 횟수를 출력 합니다.
  2. 10회 이동시 각 스텝마다, 50% 확률로 랜덤하게 이벤트가 발생합니다.(발생 시키는 부분도 구현하셔야 합니다.)
    각 스텝마다 이벤트 발생(이벤트함수를 따로 생성해서 진행해주세요.)여부를 출력합니다.
  3. 10회 이동후에는 총 이동거리와 총 이벤트 발생횟수를 출력 합니다.

구현

필수 기능 구현

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


#include "MyActor.h"
#include "Engine/Engine.h"

// Sets default values
AMyActor::AMyActor()
{
 	// 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 AMyActor::BeginPlay()
{
	Super::BeginPlay();

	GetWorld()->GetTimerManager().SetTimer(TimerHandle, this, &AMyActor::RepeatFunctions, 3.0f, true);
}

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

}

void AMyActor::PrintCurrentLocation()
{
	FVector ActorLocation = GetActorLocation();
	if (GEngine)
	{
		GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Blue, FString::Printf(TEXT("Actor : %s"), *GetName()));
		GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Blue, ActorLocation.ToString());
	}
}

void AMyActor::Turn()
{
	float RValue1, RValue2, RValue3;
	FRotator newRot = GetActorRotation();

	RValue1 = FMath::RandRange(-90.0f, 90.0f);
	RValue2 = FMath::RandRange(-90.0f, 90.0f);
	RValue3 = FMath::RandRange(-90.0f, 90.0f);
	
	newRot.Add(RValue1, RValue2, RValue3);

	SetActorRotation(newRot);
}

void AMyActor::Move()
{
	int32 RValue1, RValue2, RValue3;
	FVector newLoc = GetActorLocation();

	RValue1 = FMath::RandRange(-100, 100);
	RValue2 = FMath::RandRange(-100, 100);
	RValue3 = FMath::RandRange(-100, 100);

	newLoc += FVector(RValue1, RValue2, RValue3);

	SetActorLocation(newLoc);
}

void AMyActor::RepeatFunctions()
{
	Count++;
	Turn();
	Move();
	PrintCurrentLocation();

	if (Count >= 10)
	{
		GetWorld()->GetTimerManager().ClearTimer(TimerHandle);
		GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Blue, TEXT("Repeat End"));
	}
}

도전 기능 구현

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


#include "MyActor.h"
#include "Engine/Engine.h"

// Sets default values
AMyActor::AMyActor()
{
 	// 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 AMyActor::BeginPlay()
{
	Super::BeginPlay();

	GetWorld()->GetTimerManager().SetTimer(TimerHandle, this, &AMyActor::RepeatFunctions, 3.0f, true);
}

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

}

// 액터의 현재 위치 출력
void AMyActor::PrintCurrentLocation()
{
	FVector ActorLocation = GetActorLocation();
	if (GEngine)
	{
		GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Blue, FString::Printf(TEXT("Actor Location : %s"), *ActorLocation.ToString()));
	}
}

// 랜덤 값만큼 액터 회전
void AMyActor::Turn()
{
	float RValue1, RValue2, RValue3;
	FRotator newRot = GetActorRotation();

	RValue1 = FMath::RandRange(-90.0f, 90.0f);
	RValue2 = FMath::RandRange(-90.0f, 90.0f);
	RValue3 = FMath::RandRange(-90.0f, 90.0f);
	
	newRot.Add(RValue1, RValue2, RValue3);

	SetActorRotation(newRot);
}

// 랜덤 값만큼 액터 이동
void AMyActor::Move()
{
	int32 RValue1, RValue2, RValue3;
	FVector newLoc = GetActorLocation();

	RValue1 = FMath::RandRange(-100, 100);
	RValue2 = FMath::RandRange(-100, 100);
	RValue3 = FMath::RandRange(0, 100);

	newLoc += FVector(RValue1, RValue2, RValue3);
	MovedDistance += FVector::Dist(GetActorLocation(), newLoc);
	SetActorLocation(newLoc);
}

// 이벤트 함수
void AMyActor::Event()
{
	GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Red, TEXT("Event Occur!"));
	EventCount++;
}

// 랜덤으로 이벤트 실행
void AMyActor::PlayEventRandom(int32 percent) {
	int RValue = FMath::RandRange(1, 100);
	if (RValue <= percent) {
		Event();
	}
}

// 반복 실행 함수
void AMyActor::RepeatFunctions()
{
	Count++;
	Turn();
	Move();
	PrintCurrentLocation();
	PlayEventRandom(50);

	if (Count >= 10)
	{
		GetWorld()->GetTimerManager().ClearTimer(TimerHandle);

		GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Blue, FString::Printf(TEXT("Moved Distance : %f"), MovedDistance));
		GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Blue, FString::Printf(TEXT("Event Occured : %d"), EventCount));
		GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Blue, TEXT("Repeat End"));
	}
}

동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.

 

트러블 슈팅

 

문제: 헤더파일을 불러오지 못하는 현상

해결 방법: 플러그인 설치를 해제하니까 해결이 되었다.

 

문제: AddOnScreenDebugMessage 에서 ActorLocation을 출력하는데 컴파일에러가 뜸

 

해결 방법: printf에서 %s는 (TCHAR)* 를 기대했는데 FString 타입이 왔다.

*로 디레퍼런스하여 해결하였다.

GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Blue, FString::Printf(TEXT("Actor Location : %s"), *ActorLocation.ToString()));