본문 바로가기

게임 개발/이득우의 언리얼 C++

[이득우의 언리얼 C++ 게임개발의 정석] #3. 움직이는 액터의 제작

반응형

이득우의-언리얼-C++-게임개발의-정석-표지

1. 프로그래밍 환경을 편리하게 만들어줄 매크로를 설정하고,

이를 사용해 게임에서 액터가 어떻게 생성되고, 액터에서 어떤 이벤트가 발생하는지 확인해 본다.

2. 로직을 구현해 움직임을 부여하기 / 로직 없이 무브먼트 컴포넌트로 움직임 부여하기 학습

 

<1>. 로깅 환경의 설정

움직이는 액터를 제작하려면 액터의 생성 과정을 알아야 함 → 중간중간 로그를 띄우게 하여 프로세스를 엿볼 수 있다.

<1> - 1. 출력 로그 윈도우 : 'UE_LOG' - (출력 로그에서 확인 가능)

더보기

UE_LOG(카테고리, 로깅 수준, 형식 문자열, 인자... )

  • 카테고리 : 로그를 분류하기 위해
  • 로깅 수준 : 에러(Error) = 빨간색, 경고(Warning) = 노란색, 메시지(Log) = 흰색

 에디터의 출력 로그 윈도우에는 필터 기능이 있어서, 원하는 로깅 수준 / 카테고리만 볼 수 있다.

  • 형식 문자열 : printf 함수랑 비슷한 기능. / 문자열을 관리하는 기본 클래스는 FString. FString 변수에서 문자열 정보를 얻어오려면 반드시 * 연산자를 앞에 지정해줘야 함.
FString::Printf(TEXT("Actor Name : %s, ID : %d, Location X : %.3f"), *GetName(), ID, 
                                                                    GetActorLocation().X);

 

기존의 다양한 로그 카테고리가 있지만, 우리가 직접 로그 카테고리를 선언해 보자. → 언리얼 엔진은 직접 로그 카테고리를 선언하기 위해 2 개의 매크로를 제공한다 → 하나는 헤더파일, 하나는 소스 파일 위에 선언한다.

 

※해당 로그 매크로를 'ArenaBattle.h'에 선언하고 모듈의 모든 헤더들이 이 헤더를 참조하도록 구성.

//ArenaBattle.h

#include "EngineMinimal.h"

DECLARE_LOG_CATEGORY_EXTERN(ArenaBattle, Log, All);

 

//ArenaBattle.cpp

#include "ArenaBattle.h"
#include "Modules/ModuleManager.h"

DEFINE_LOG_CATEGORY(ArenaBattle);

...

 

분수대 액터 선언(Fountain.h)에서도 "EngineMinimal.h" 대신 "ArenaBattle.h"을 참조한다. 

 

게임이 시작되고 가장 먼저 실행되는 BeginPlay 함수에 로그를 출력하여 보자.

//Fountain.cpp

void AFountain::BeginPlay()
{
	Super::BeginPlay();
    
    UE_LOG(ArenaBattle, Warning, TEXT("Actor Name : %s, ID : %d, Location X : %.3f"),
                                 *GetName(), ID, GetActorLocation().X);
     ...
}

 

→ 현재 배치된 분수대 액터의 수만큼 로그가 출력되는 것을 볼 수 있다. 

 

<2>. 어설션 : 반드시 확인하고 넘어가야 하는 점검 코드 (가벼운 경고 = ensure)

<3>. 액터의 주요 이벤트 함수

 

※이벤트 함수 : 언리얼 엔진에 의해 자동으로 호출되는 중요한 함수

  • PostInitializeComponents : 액터의 모든 컴포넌트 세팅이 완료된 후에 호출
  • BeginPlay : 게임에 참여할 때
  • Tick : 매 프레임마다 호출
  • EndPlay : 액터가 게임에서 퇴장할 때 호출

<4>. 움직이는 액터의 설계 : Tick 함수를 사용해 액터의 움직임을 구현하기

회전할 각속도의 값을 변수로 지정 → 에디터에서 편집할 수 있게 UPROPERTY에 EditAnywhere 추가 → 객체 지향 언어 설계의 중요한 원칙인 '데이터 은닉'을 위해 private로 선언 !!! 그럼 에디터에서 값을 변경할 수 없음 → UPROPERTY 매크로에 AllowPrivateAccess라는 META 키워드 추가 → 편집함과 동시에 데이터 은닉 가능

private:
	UPROPERTY(EditAnywhere, Category=Stat, Meta = (AllowPrivateAccess = true))
        float RotateSpeed;

 

RotateSpeed 속성의 기본값을 생성자에서 초기화시킴   Tick함수에는 AddActorLocalRotation 함수를 이용해 틱마다 회전하도록 함.

//Fountain.cpp

AFountain::AFountain()
{
	RotateSpeed = 30.0f;
}

void AFountain::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
    AddActorLocalRotation(FRotator(0.0f, RotateSpeed * DeltaTime, 0.0f));
 }

 

  • Pitch = Y축 회전
  • Yaw = Z축 회전
  • Roll = X축 회전

<5>. 무브먼트 컴포넌트의 활용

※ 무브먼트 컴포넌트 : 액터와 움직임이라는 요소를 분리해 별도로 관리하는 프레임워크.

 

위에서는 Tick함수를 썼지만, 무브먼트 컴포넌트를 사용하면 쓰지 않아도 된다.

-무브먼트 컴포넌트의 종류

  • FloatingPawnMovement : 중력의 영향을 받지 않는 움직임.
  • RotatingMovement : 지정한 속도로 액터 회전
  • InterpMovement : 지정한 위치로 액터 이동
  • ProjectileMovement : 중력의 영향을 받아 포물선을 그리는 발사체. ex)총알, 미사일
//Fountain.h

#include "GameFramework/RotatingMovementComponent.h"  //무브먼트 컴포넌트 가져오기

class ARENABATTLE_API Fountain : public AActor
{
	...
    UPROPERTY(VisibleAnywhere)
    URotatingMovementComponent* Movement;
    ...
}

!!Tick 기능을 제거함.

//Fountain.cpp

AFountain::AFountain()
{
	PrimaryActorTick.bCanEverTick = false; //Tick 기능 제거하기!!!
    
    ...
    Movement = CreateDefaultSubobject<URotatingMovementComponent>(TEXT("MOVEMENT"));
    
    ...
    Movement->RotationRate = FRotator(0.0f, RotateSpeed, 0.0f);
}

<6>. 프로젝트의 재구성

액터 추가는 쉽게 할 수 있지만 액터 제거 메뉴는 없다. 수동으로 제거하는 법을 알아보자

 

  1. .vs, Binaries, Interdediate, ArenaBattle.sln 파일을 제거한다.
  2. 게임 프로젝트의 Source 폴더 내에 위치한 ArenaBattle 폴더에 있는 Fountain.h와 Fountain.cpp 파일을 삭제한다. 이 때, 반드시 탐색기에서 관련 파일을 제거해야 한다.
  3. 게임 프로젝트의 uproject 파일을 우클릭하고 Generate Visual Studio project files 메뉴를 선택해 비주얼 스튜디오 프로젝트를 재생성한다.
 

[이득우의 언리얼 C++ 게임개발의 정석] #4. 게임플레이 프레임워크

게임이 시작되려면 게임의 규칙, 플레이어, 플레이어가 조종하는 액터가 있어야 한다.이는 각각 게임 모드, 플레이어 컨트롤러, 폰에 대응한다.이 3가지 액터를 직접 제작하고 학습해 보자.. 게

lbto.tistory.com

 

반응형