스마트 포인터 라이브러리는 C++ 오브젝트를 편리하게 관리하기 위해 사용

 

TUniquePtr

지정한 곳에서만 메모리를 관리하는 포인터

특정 오브젝트에게 명확한 포인터 해제 권한을 줄 때

 

TSharedPtr

더 이상 참조되지 않으면 자동으로 메모리를 해제하는 포인터

다른 함수로부터 할당된 오브젝트를 Out으로 받는 경우

Null 가능

 

TSharedRef

TSharedPtr와 동일하지만 유효한 객체(Not Null)를 보장

여러 로직에서 할당한 오브젝트가 공유해서 사용되는 경우

 

TWeakPtr

약한 참조를 저장하는 포인터

순환 참조 문제를 해결하기 위해 사용

객체가 이미 소멸되었는지 확인 가능

 

UObject는 가비지 컬렉터에서 이미 관리되고 있기 때문에 C++ 오브젝트에만 사용해야 함

'언리얼 > 언리얼 C++ 및 개념' 카테고리의 다른 글

언리얼 개념 모음  (2) 2024.12.19
언리얼 C++ 코딩 규칙  (1) 2024.12.10
언리얼 C++ 기본 타입과 문자열  (0) 2024.12.10
언리얼 엔진 게임 프레임워크  (1) 2024.09.03
언리얼 빌드 시스템  (0) 2024.07.24

스태틱 메시

스태틱 메시는 움직이지 않는 고정된 3D 모델

비디오 메모리(GPU에 탑재된 메모리)에 캐시되어 빠른 렌더링이 가능하므로 이동, 회전, 스케일이 가능

 

파티클 시스템

이펙트, 날씨 등을 만드는 도구

 

Transient

언리얼 엔진의 프로퍼티 지정자

메모리에만 존재하여 저장(세이브/로드)되지 않음

 

0.0f와 같이 소수점 리터럴에 f를 붙이는 이유

기본적으로 소수점 리터럴이 double로 해석되므로 타입을 명시적으로 float으로 지정하기 위해서

float 변수에 double 값을 할당하면 암시적 형변환 비용 감소

 

UFUNCTION 매크로 지정자

BlueprintCallable

블루프린트 그래프에서 호출이 가능하지만 C++ 코드 편집 없이 변경이나 덮어쓰기가 불가능

 

BlueprintImplementableEvent

C++이 아닌 블루프린트 그래프에서 작성되는 것

프로그래머가 아닌 개발자에게 기능을 제작하기 위해 사용

 

BlueprintNativeEvent

C++로 기본 작동 방식을 프로그래밍하지만 블루프린트 그래프로 덮어쓸수 있음

이름 끝에 _Implementation이 붙는 가상 함수가 생성됨

 

exec

콘솔에 액세스할 수 있는 함수로 지정

 

UPROPERTY의 Meta에 Categories 지정

카테고리에 맞게 프로퍼티를 분류

 

GameInstance

컨텐츠를 담는 어플리케이션의 뼈대

어플리케이션마다 하나씩 싱글톤으로 관리됨

게임이 실행되는 동안 유지되고 게임 상태 및 전역 설정을 관리하는데 사용

 

Assertion 함수

check

false일 경우 에디터가 종료되고 crash reporter에 원인이 로그에 뜸

중요한 부분에 검증을 하는 것이 중요

실제 게임으로 빌드할 때는 사라짐

 

ensure

에디터가 종료되지 않고 콜스택을 생성

 

ensureMsgf

ensure 기능 + 메시지를 남길 수 있는 매크로

https://dev.epicgames.com/documentation/ko-kr/unreal-engine/epic-cplusplus-coding-standard-for-unreal-engine?application_version=5.1

 

프로젝트마다 다르지만 언리얼 엔진 코딩 표준을 지켜 한 사람이 만든 것처럼 통일해야 유지보수 시간을 줄일 수 있음

 

언리얼 규칙

파스칼 케이싱(Pascal Casing) :  합성어의 첫 글자를 대문자를 사용해 명명, ex) UnrealEngine

일반적으로 단어 사이에 언더스코어(_)를 사용하지 않음

템플릿, 인터페이스 클래스에 접두사 T

UObject(언리얼 오브젝트)를 상속받는 클래스는 접두사 U를 추가

AActor를 상속받는 클래스는 접두사 A

UI를 제작할 때 사용되는 Slate(UI 전용 클래스)를 상속받는 클래스는 접두사 S

추상적 인터페이스 클래스는 접두사 I,

열거형 변수는 접두사 E

bool 변수는 접두사 b

그 외 대부분 클래스, 구조체는 접두사 F

함수 파라미터가 참조로 전달된 후 함수가 그 값에 쓸 것으로 예상하는 경우 이름 앞에 Out 접두사를 추가하여 파라미터의 용도를 명시

 

C++ 규칙

int는 자료형의 크기가 플랫폼에 따라 변할 수 있으므로 int8/int16처럼 정확한 타입 크기를 지정

char->TCHAR

C++ 표준 라이브러리(STL)는 사용하지 않고 TArray, TSet, TMap을 사용

const를 사용할 수 있으면 사용하여 const를 보고 변경하면 안되는 변수로 파악, 컴파일 타임에 코드 정확성 증가

c++ 17까지 지원

auto를 웬만하면 사용하지 말고, 람다/iterator(장황해서 가독성을 해칠 때)만 사용

move 대신 유사한 MoveTemp 사용(UObject도 지원)

 

if 구문이 한 줄이어도 중괄호 사용

if (bHaveUnreallicense)
{
	...
}

 

파일 이름에는 접두사를 쓰지 않음

헤더에 #pragma once 반드시 지정하여 중복된 헤더를 다시 복사하지 않게 함

무분별하게 include할 경우 컴파일 시간 증가하므로 헤더에 include를 세밀하게 지정하고 전방선언 사용 권장

헤더의 static 변수를 선언하게 될 경우 이 헤더를 include하는 모든 인스턴스들이 중복으로 컴파일 되므로 헤더에 extern으로 선언하고 cpp에 정의하도록 변경

인터페이스 클래스에 멤버 변수를 가급적 선언하지 않기

 

사용자는 public 인터페이스를 많이 사용하기 때문에 public 인터페이스를 먼저 선언한 후 private 선언이 뒤따라야 함

class MyClass{
public:
	...
private:
	...
};

 

프로젝트 소스코드 폴더 규칙

  • Game : 게임 모드와 게임 설정에 관련된 클래스
  • Player : 플레이어에 관련된 클래스
  • Character : 기본 캐릭터와 PC 및 NPC에 관련된 클래스
  • Gimmick : 기믹 배경 물체에 관련된 클래스
  • Input : 플레이어 입력에 관련된 클래스
  • Action : 캐릭터 액션에 관련된 클래스
  • Item : 캐릭터 아이템에 관련된 클래스
  • Stat : 캐릭터 스텟에 관련된 클래스
  • AI : NPC 인공지능에 관련된 클래스
  • UI : UI에 관련된 클래스
  • Physics : 물리 충돌체 설정에 관련된 전처리기
  • Interface : 인터페이스 클래스를 모아둔 폴더

 

클래스 생성 규칙

  • 모든 클래스는 프로젝트의 약자 접두사로 시작
  • 폴더마다 다른 폴더와의 의존성을 최소화
  • 다른 폴더의 클래스에 접근할 때 가급적 인터페이스를 통해 접근
    • 가급적 다른 폴더의 헤더를 직접 참조하지 않도록 구성하는 것이 바람직
  • 헤더 경로를 찾기 쉽도록 모듈.Build.cs 파일에 모듈의 폴더를 인클루드 경로에 설정
    • PublicIncludePaths.AddRange(new string[] {"모듈이름"}); 추가

'언리얼 > 언리얼 C++ 및 개념' 카테고리의 다른 글

언리얼 스마트 포인터  (1) 2024.12.30
언리얼 개념 모음  (2) 2024.12.19
언리얼 C++ 기본 타입과 문자열  (0) 2024.12.10
언리얼 엔진 게임 프레임워크  (1) 2024.09.03
언리얼 빌드 시스템  (0) 2024.07.24

플랫폼 파편화 : C++의 함수가 특정 플랫폼에서 다르게 동작하는 문제

int 타입 크기를 지정하는 이유

메모리 정렬과 패딩을 고려할 때 타입 크기를 정확히 아는 것이 중요

통신할 때 타입 크기가 모호할 경우 안정적이지 못함

데이터 통신에서 바이너리 데이터를 주고 받을 때 uint8을 사용하는 것이 일반적

bool은 크기가 명확하지 않아 멤버 변수로 bool 대신 uint8로 선언하고 BitFieldOperator를 1bit로 선언해 데이터 양을 최소화

uint8 bIsBoolean:1;

 

TCHAR : Single Byte, MultiByte, Unicode 세 가지 타입에 신경쓸 필요 없이 처리해줌

 

https://dev.epicgames.com/documentation/ko-kr/unreal-engine/character-encoding-in-unreal-engine?application_version=5.1

 

언리얼은 모두 UTF-16(한 문자당 2바이트) 포맷을 사용

일반적으로 소스 코드에 문자열을 그대로 쓰는 것을 추천하지 않음

소스 코드에 한글을 사용할 때는 UTF-8을 가급적 사용

 

FString

https://dev.epicgames.com/documentation/ko-kr/unreal-engine/fstring-in-unreal-engine?application_version=5.1

 

TChar의 동적 배열(TArray)을 소유하는 클래스

*연산자를 사용하여 TChar 포인터를 반환

 

C 런타임 수준에서 문자열을 처리하는 함수(strstr 등)은 FString을 통해 처리

 

다른 타입에서 FString으로의 변환 함수

// 포맷 지정자를 통해 String 생성 가능
FString::Printf(TEXT("Score: %d"), Score);  // "Score: 100"

// 부동소수점을 문자열로 변환 (불필요한 0 제거)
FString::SanitizeFloat(3.14000);  // "3.14"

// 정수를 문자열로 변환 
FString::FromInt(42);  // "42"

 

다양하게 String을 조작하려면 FString을 사용

 

UE_LOG 매크로의 세 번째 파라미터에는 배열이기 때문에 %s로 배열을 전달

%s에 대응될 때는 TCHAR의 포인터를 전달해야 하는데, FString에 포인터 연산자 사용

FString LogCharString = LogCharArray;
UE_LOG(LogTemp, Log, TEXT("%S"), *LogCharString);

 

FName

https://dev.epicgames.com/documentation/ko-kr/unreal-engine/fname-in-unreal-engine?application_version=5.1

 

애셋 관리를 위해 사용되는 문자열 체계

에셋 키를 지정하는 용도로 사용되고 빌드시 해시값으로 변환하여 빠르게 찾을 수 있도록 함

대소문자 구분이 없고 한 번 선언되면 해시 키로 생성되기 때문에 변경하기 위해 FString으로 변환하면 데이터가 깨질 수 있음

 

언리얼에서 FName과 관련된 전역 Pool 자료구조를 갖고 있음

FName에서 문자열을 해시 값으로 변환하여 보관하고 전역 Pool에서 검색해 반환

 

FText

UI에서 다국어 지원을 위한 문자열 관리 체계

문자열 테이블 정보가 추가로 요구됨

게임 빌드시 자동으로 다양한 국가별 언어로 변환됨

 

TEXT 매크로

문자열 리터럴을 유니코드로 변환하여 플랫폼 간 호환성을 유지

FString과 FName에 멀티바이트 문자열(문자열 리터럴)로 설정할 경우 인코딩 방식에 의해 깨질 수 있으므로 TEXT 매크로 사용하는 것이 바람직

 

'언리얼 > 언리얼 C++ 및 개념' 카테고리의 다른 글

언리얼 개념 모음  (2) 2024.12.19
언리얼 C++ 코딩 규칙  (1) 2024.12.10
언리얼 엔진 게임 프레임워크  (1) 2024.09.03
언리얼 빌드 시스템  (0) 2024.07.24
언리얼 오브젝트 패키지  (0) 2024.07.23

게임플레이 프레임워크

 

게임

월드

  • 게임 컨텐츠를 담기 위한 가상의 공간
  • 시간, 트랜스폼, 틱을 제공
  • 월드 세팅이라는 컨텐츠 제작을 위한 기본 환경 설정 제공
  • 기본 단위는 액터

 

게임 모드

오직 서버에만 존재

언리얼 엔진에서 하나의 게임에는 반드시 하나의 게임 모드만 존재

게임 규칙을 지정하고 판정하는 최고 관리자 액터, 형태가 없음

게임 모드에서 입장할 사용자의 규격을 지정할 수 있음

 

게임모드가 관리하는 정보

현재 게임에 참여하고 있는 플레이어의 수

플레이어가 게임에 입장하는 방법과 스폰, 리스폰 규칙

게임에 관련된 중요한 처리 : 스코어에 관련된 로직 처리 등

 

게임 스테이트

서버와 모든 클라이언트에 존재

클라이언트는 게임 스테이트를 사용해 현재 게임의 상태를 파악할 수 있음

 

게임 스테이트가 관리하는 정보

현재 월드의 시간

플레이어 스테이트의 배열

 

기믹

  • 게임 진행을 위한 이벤트를 발생시키는 사물 액터
  • 주로 이벤트 발생을 위한 충돌 영역(트리거) 설정
  • 트리거를 통해 캐릭터와 상호 작용하고, 월드에 액터를 스폰해 컨텐츠 전개

 

플레이어

  • 게임에 입장한 사용자 액터, 형태가 없음
  • 게임 모드의 로그인을 통해 사용자가 게임 월드에 입장하면 플레이어 생성됨
  • 싱글 플레이 게임에는 0번 플레이어가 설정됨
  • 사용자와의 최종 커뮤니케이션 담당

 

플레이어 스테이트

서버와 모든 클라이언트에 존재

클라이언트는 플레이어 스테이트를 사용해 플레이어의 상태를 파악할 수 있음

다른 사람들과 공유할 플레이어 정보를 관리하는 데 유용

 

  • 길찾기를 사용할 수 있으며 기믹 및 다른 폰과 상호 작용
  • 폰 중에서 인간형 폰을 별도로 캐릭터라고 지칭

 

Actor

독립적으로 동작하는 개체를 나타내는 개념

게임 월드에 배치될 수 있는 모든 객체를 의미

독자적인 동작과 상태를 가질 수 있음

다른 Actor들과 상호작용 가능

 

게임 제작 과정

1. 월드 설정과 게임 모드 생성

2. 플레이어 폰의 입출력 및 모션 설정

3. 캐릭터에 반응하는 기믹 설계

4. 게임 데이터와 NPC 인공 지능

5. UI 연동 및 게임 제작 마무리

'언리얼 > 언리얼 C++ 및 개념' 카테고리의 다른 글

언리얼 C++ 코딩 규칙  (1) 2024.12.10
언리얼 C++ 기본 타입과 문자열  (0) 2024.12.10
언리얼 빌드 시스템  (0) 2024.07.24
언리얼 오브젝트 패키지  (0) 2024.07.23
언리얼 오브젝트 직렬화  (0) 2024.07.20

언리얼 엔진의 구성

에디터

게임 제작을 위해 제공되는 응용 프로그램

게임 개발 작업을 위해 다양한 폴더와 파일 이름 규칙이 미리 설정됨

프로젝트 폴더의 uproject 확장자 파일을 실행하면 에디터가 실행됨

프로젝트.uproject 파일에 버전 정보가 JSON 형식으로 있음

uproject 확장자는 윈도우 레지스트리에 등록됨, 등록이 안되어 있으면 런처를 실행해 등록

 

게임 빌드

EXE 파일과 리소스로 이루어진 독립적으로 동작하는 게임 클라이언트

 

폴더

Config : 프로젝트 설정에 필요한 정보를 보관

Content : Asset 보관

DerivedDataCache : 에셋들의 주요 정보를 미리 캐싱, 로딩 속도에 도움, 삭제 가능

Intermediate : 임시적으로 사용되는 중간 결과물을 보관, 삭제 가능

Saved : 임시로 무언가를 저장하는 용도, 의도적으로 데이터를 저장하지 않았으면 삭제 가능

 

블루프린트 프로젝트

C++ 코드가 없는 언리얼 프로젝트

언리얼 엔진이 제공하는 기본 기능을 활용해 게임을 제작하는 프로젝트

언리얼 엔진은 게임 제작에 필요한 기능을 모듈이라는 단위로 제공

언리얼 엔진의 모듈을 상속받아 블루프린트를 활용해 모든 기능과 로직을 구현하는 방식

 

블루프린트 프로젝트 추가 방법
1. 빈 폴더에 프로젝트이름.uproject 파일 추가
2. Json 형식으로 버전 추가 후 실행

{
	"FileVersion" : 3,
	"EngineAssociation" : "5.1"
}

 

언리얼 C++ 프로젝트

언리얼 엔진 C++ 모듈에 개발자가 추가로 자신만의 C++ 모듈을 추가할 수 있음

 

언리얼 C++ 모듈

언리얼 엔진의 소스코드는 모듈 단위로 구성됨

모듈을 컴파일하여 에디터 및 게임에 로직 공급

 

에디터용 DLL, 게임용 정적 라이브러리

에디터용 모듈의 이름 규칙은 UnrealEditor-{모듈이름}.DLL

 

에디터 모듈(DLL)을 빌드 폴더(Binaries/Win64)에 넣어야 C++ 모듈을 추가해 에디터를 실행

빌드된 모듈 목록이 있는 UnrealEditor.modules 파일도 같은 폴더에 넣어야 함

uproject에 모듈 이름을 지정하고 에디터 실행

 

언리얼 C++ 모듈 추가 방법
1. Binary/Win64에 모듈 추가
2. uproject에 모듈 추가

{
	"FileVersion" : 3,
	"EngineAssociation" : "5.1"
	"Modules" : [
		{
			"Name" : "UnrealSerialization",
			"Type" :	"Runtime"
		}
	]
}

 

모듈 C++ 코드 관리

언리얼 엔진 소스 코드 구조는 멀티 플랫폼 빌드를 지원하기 때문에 특정 프로그램의 구조를 따르지 않고 언리얼만의 규칙을 가짐

실제 빌드를 진행하는 주체는 Unreal Build Tool C# 프로그램

 

Soruce 폴더 구조

타겟 설정 파일 필요

전체 솔루션이 다룰 빌드 대상을 지정

{프로젝트이름}.Target.cs : 게임 빌드 설정

{프로젝트이름}Editor.Target.cs : 에디터 빌드 설정

 

모듈 폴더

모듈 설정 파일 : {모듈이름}.build.cs

보통은 프로젝트 이름으로 모듈 이름을 지정

모듈을 빌드하기 위한 C++ 프로젝트 설정 정보

외부 라이브러리에서 제공하는 헤더가 담긴 폴더 정보 및 함께 링크할 라이브러리 정보 지정

소스 코드 파일

 

모듈 이름으로 된 헤더와 소스 파일을 지정

 

모듈 뼈대를 매크로를 통해 제작

IMPLEMENT_MODULE : 유용한 기능을 제공해주는 c++ 코드 라이브러리

IMPLEMENT_GAME_MODULE : 게임 제작에 관련있는 모듈

IMPLEMENT_PRIMARY_GAME_MODULE : 전체적인 게임을 동작하는 데 사용하는 로직들을 모아둔 모듈, 일반적으로 게임이 만들어지기 위해서는 선언해야 함

 

uproject 파일 우클릭 후 generate visual studio project files 메뉴를 선택하면 언리얼 버전 셀렉터가 언리얼 빌드 툴을 가동해 intermediate 폴더에 관련된 프로젝트 파일을 자동으로 생성해 줌

 

C#을 사용하는 이유는 C#은 실행 중에 코드를 바로 컴파일하고 결과를 반영할 수 있음

// UnrealBuildSystmeEditor.Target.cs

using UnrealBuildTool;
using System.Collections.Generic;

// 클래스 이름을 모듈이름EditorTarget으로 지정해야 함
public class UnrealBuildSystemEditorTarget : TargetRules
{
    public UnrealBuildSystemEditorTarget(TargetInfo Target) : base(Target)
    {
        // 타입 정보를 에디터로 명시해야 함
        Type = TargetType.Editor;
        DefaultBuildSettings = BuildSettingsVersion.V2;
        IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_1;
        ExtraModuleNames.Add("UnrealBuildSystem");
    }
}

 

// UnrealBuildSystem.Build.cs

using UnrealBuildTool;

// 모듈 이름을 클래스로 지정
public class UnrealBuildSystem : ModuleRules
{
    public UnrealBuildSystem(ReadOnlyTargetRules Target) : base(Target)
    {
        PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

        // 언리얼 엔진이 제공하는 기본 모듈들, 필수
        PublicDependencyModuleNames.AddRange(new string[]{ "Core", "CoreUObject", "Engine", "InputCore", "CommonUtility" });

        PrivateDependencyModuleNames.AddRange(new string[]{ });

        // Uncomment if you are using Slate UI
        // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });

        // Uncomment if you are using online features
        // PrivateDependencyModuleNames.Add("OnlineSubsystem");

        // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
    }
}

 

// UnrealBuildSystem.cpp
#include "UnrealBuildSystem.h"
#include "Modules/ModuleManager.h"

// FDefaultGameModuleImpl는 언리얼이 제공하는 게임 모듈 기본 클래스
IMPLEMENT_PRIMARY_GAME_MODULE(FDefaultGameModuleImpl, UnrealBuildSystem, "UnrealBuildSystem");

 

모듈 종속 관계

만든 모듈도 언리얼 엔진이 만든 모듈을 활용해야 함

언리얼 엔진이 제공하는 모듈 사이에 종속 관계가 있음

 

하나의 모듈에 너무 많은 코드가 들어가면 언리얼 엔진이 빌드 방식을 변경함

프로젝트가 커질수록 모듈을 나누어서 관리하는 것이 유리

 

모듈 내 소스를 필요한 만큼만 공개해야 모듈 간 의존성을 줄이고 컴파일 타임을 최소화

공개할 파일은 모두 public 폴더, 숨길 파일은 모두 private 폴더로

공개할 클래스나 함수에 모듈이름_API 매크로를 선언하여 다른 모듈에 노출할지 추가로 지정해야 함

 

build.cs에 서브 모듈 이름만 넣어주면 public 폴더의 include 디렉토리와 라이브러리를 링크할 수 있도록 언리얼 빌드 툴이 자동으로 설정

주 게임 모듈을 참조할 다른 모듈이 있는 것은 좋지 않으므로 주 게임 모듈 안에서 public / private 나눌 필요는 없음

 

플러그인 시스템

게임 프로젝트 소스에 모듈을 추가하는 방법은 분업이 어렵다는 단점

공용 기능들을 모아둔 모듈은 프로젝트로부터 독립적으로 동작

다수의 모듈과 게임 컨텐츠를 포함하는 포장 단위

에디터 설정을 통해 유연하게 플러그인을 추가하거나 삭제할 수 있음

 

구조

uplugin 파일

Resource 폴더, 에디터 메뉴용 아이콘

컨텐츠

모듈 폴더

 

마켓 플레이스 판매로도 이어질 수 있도록 여러 설정을 추가할 수 있음

 

게임 빌드

게임 타겟 설정을 추가하면 게임 빌드 옵션이 추가됨

게임 타겟으로 빌드된 모듈은 정적 라이브러리로 실행 파일에 포함됨

게임이 실행되기 위해서는 실행 파일과 컨텐츠 에셋이 함께 있어야 함

빌드 : 실행 파일을 생성하기 위한 컴파일

쿠킹 : 지정한 플랫폼에 맞춰 컨텐츠 에셋을 변환하는 작업

패키징 : 이들을 모두 모아서 하나의 프로그램으로 만드는 작업

 

Shipping 빌드

사용자에게 배포할 최종 게임의 코드를 만들어내는 작업

check, ensure 같은 assertion 매크로들이 제외됨

platfrom의 shipping 설정 후 Package Project 메뉴 클릭

+ Recent posts

목차