이 문서에는 언리얼엔진을 이용한 나의 설계 경험을 정리한다.
(문서의 내용은 결정된 내용이 아니고, 지속적으로 개선될 것이다.)
언리얼 엔진 C++ 개발의 기본적인 프로그래밍 컨벤션은 다음 문서를 참고한다.
docs.unrealengine.com/en-US/ProductionPipelines/DevelopmentSetup/CodingStandard/index.html
게임 내 커스텀 Enum 데이터 타입들을 모아놓을 클래스 파일을 생성한다.
언리얼 작업중에는 직접 제작한 다양한 열거형 타입들을 사용하게 될 것이다.
이 데이터 타입들 중에서는 특정 클래스에 귀속되어야하는 타입도 존재하겠지만, 글로벌하게 사용되는 공통 데이터 타입들도 분명 존재한다. 그리고 구현 단계에서는 그 경계를 명확히 지정하기 어렵기 때문에 playground로서의 클래스파일이 하나 필요하다.
ex)
// 빈 클래스class DataTypes
{
public:
DataTypes();
~DataTypes();
};
UENUM(BlueprintType)
enum class EEnemyAIType : uint8
{
Tank UMETA(DisplayName = "Tank"),
Healer UMETA(DisplayName = "Healer"),
Ranged UMETA(DisplayName = "Ranged"),
Rusher UMETA(DisplayName = "Rusher"),
Disabler UMETA(DisplayName = "Disabler")
};
UENUM(BlueprintType)
enum class EGameState : uint8
{
MainMenu UMETA(DisplayName = "MainMenu"),
LevelSelectionMenu UMETA(DisplayName = "LevelSelectionMenu"),
LoadingScreen UMETA(DisplayName = "LoadingScreen"),
LoadOutMenu UMETA(DisplayName = "LoadOutMenu"),
InGameHUD UMETA(DisplayName = "InGameHUD"),
MissionSummary UMETA(DisplayName = "MissionSummary"),
Unassigned UMETA(DisplayName = "Unassigned"),
};
// ...
게임 내 커스텀 Struct 데이터 타입들을 모아놓을 클래스 파일을 생성한다.
열거형과 마찬가지의 이유로 구조체도 따로 모아놓을 클래스 파일이 필요하다.
class CustomStructs
{
public:
CustomStructs();
~CustomStructs();
};
USTRUCT(BlueprintType)
struct FBossAIData
{
GENERATED_BODY()
public:
FBossAIData()
:
AIType(EEnemyAIType::Tank)
{}
FBossAIData(EEnemyAIType InAIType, FName InDataTableRowName)
:
AIType(InAIType),
DataTableRowName(InDataTableRowName)
{}
UPROPERTY(EditAnywhere, BlueprintReadWrite)
EEnemyAIType AIType;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FName DataTableRowName;
};
// ...
게임 내 유틸리티 함수를 모아놓을 클래스를 생성한다.
언리얼에서 작업을 진행하게 되면, 굉장히 많은 기능들과 방대한 코드 속에서 그때그때 예제를 만들며 많은 시간을 낭비하게 된다. 시간을 좀 더 효율적으로 활용하기 위해 제작해본 예제들을 기능 단위로 유틸리티 함수에 쌓아두어야 할 것이다.
유틸리티 함수는 일반화된 작업들을 수행하는 함수들로, 모두 static함수로 구성되어 있다.
화면에 직선이나 구체를 그리는 디버깅용 함수, Enum을 문자열로 변환하는 함수, 템플릿 함수 등이 이 클래스의 함수로서 들어가게 될 것이다.
ex)
class GameUtils
{
public:
GameUtils() {}
~GameUtils() {}
public:
// logsstatic void PrintHitResult(const FHitResult& InHitResult);
static bool IsValid(const UObjectBase* const InObject);
static FString GetDebugName(const UObject* const InObject);
static void DrawPoint(UWorld* InWorld, FVector InLocation, FColor InColor = FColor::Red);
static void DrawArrow(UWorld* InWorld, FVector InStart, FVector InEnd);
template<typename Type>
static Type GetRandomArrayElement(const TArray<Type>& InArray)
{
int Index = FMath::RandRange(0, InArray.Num() - 1);
return InArray[Index];
}
template<typename TEnum>
static FORCEINLINE FString GetEnumValueAsString(const FString& InEnumName, TEnum InEnumValue)
{
const UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, *InEnumName, true);
if (!EnumPtr) return FString("Invalid");
return EnumPtr->GetNameByValue((int64)InEnumValue).ToString();
}
// ...
};
GameInstance의 역할