프로그래밍 공부
작성일
2024. 4. 19. 12:50
작성자
WDmil
728x90

언리얼 C++로 만든 객체와 데이터 테이블을 연동해서 사용할 수 있게 한다.


C++로 Struct타입 제작하기.

 

Struct타입을 정의해서 데이터 테이블로 해당 데이터를 종류별로 관리할 수 있게 만들것이다.

 

#pragma once

#include "CoreMinimal.h"
#include "Weapon_Struct_Data.generated.h"

#define DPROPERTY UPROPERTY(BlueprintReadWrite, EditAnywhere)

UENUM(BlueprintType)
enum class EWeaponName : uint8
{
	SA5 UMETA(DisplayName = "SA5"),
	N33 UMETA(DisplayName = "N33"),
	R42 UMETA(DisplayName = "R42"),
	TK5 UMETA(DisplayName = "TK5"),
	RK53 UMETA(DisplayName = "RK53"),
	B19 UMETA(DisplayName = "B19"),
	D22 UMETA(DisplayName = "D22"),
	M4C UMETA(DisplayName = "M4C"),
	SM12 UMETA(DisplayName = "SM12"),
	MX9 UMETA(DisplayName = "MX9"),
	L11 UMETA(DisplayName = "L11"),
	VC30 UMETA(DisplayName = "VC30"),
};

USTRUCT(BlueprintType)
struct FWeaponAssets : public FTableRowBase
{
	GENERATED_USTRUCT_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(DisplayName = "WeaponName"))
		EWeaponName WeaponName;

		UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (DisplayName = "WeaponMesh"))
		TObjectPtr<USkeletalMesh> WeaponMesh;

		UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (DisplayName = "AssassinMeterial"))
		TObjectPtr<UMaterialInstance> AssassinMeterial;

		UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (DisplayName = "MilitaryMaterial"))
		TObjectPtr< UMaterialInstance> MilitaryMaterial;

		UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (DisplayName = "VibrantMaterial"))
		TObjectPtr< UMaterialInstance> VibrantMaterial;

		UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (DisplayName = "WhiteMaterial"))
		TObjectPtr< UMaterialInstance> WhiteMaterial;


};

Struct타입은 Cpp파일이 필요하지 않아, .h파일에서만 코드를 정의한다.

 

그러나, 언리얼 C++에서 CPP파일이 존재하지 않다면, CoreMinimal.h를 열 수 없기 때문에 남겨는 놓는다.

 

위의 StructType에 값을 정의해주고, Name과, 여러 메쉬 메테리얼 데이터를 정의해준다.

 

이 Struct타입을 데이터 테이블로 재구성하게 되면, 언할 때 이름만 넣는다면 값을 가져올 수 있을것이다.


데이터 테이블 만들기

 

데이터 테이블을 생성해준다.

 

위 데이터 테이블을 CSV파일로 관리할 것 이다.

해당데이터 테이블이 관리할 데이터 종류를 선택해준다. 

 

에셋에 이러한 형태로 관리되고 있는 경우 사용할 수 있다. 주로 데이터의 메쉬 종류나 머티리얼 종류가 여러개 일 때, 종합적으로 관리하기 쉽도록 만들어져 있다.

 

데이터 레이블의 이름을 확인한다. 이 값을 CSV파일로 정리해서 관리할 것 이다.

 

엑셀을 사용해도 되고, CSV파일을 생성할 수 있는 다른 외부 프로그램도 상관없다. 해당 데이터 레이블을 정의할 CSV파일을 생성한다.

데이터는 위와같이 정리한다.

 

Name과 WeaponName은 원하는 String으로 정의해도 되고, 위와같이 IntType으로 정의해도 된다.

 

Enum으로 데이터를 관리 및 정의하기 때문에 숫자로 정의하였다.

 

위 데이터를 임포트하여 데이터테이블에 기입하면 된다.

 

위와같이 데이터 테이블을 관리할 수 있다.

나중에 블루프린트로 사용하기도 편하고, 값을 수정해야 할 때 외부에서 수정할 수 있다.


BaseWeapon

 

위 데이터를 사용하는 Weapon의 Base를 만든다.

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

#pragma once

#include "CoreMinimal.h"
#include "Data\Weapon_Struct_Data.h"
#include "GameFramework/Actor.h"
#include "BaseWeapon.generated.h"
struct FWeaponAssets;

UCLASS()
class FTPSGAME_API ABaseWeapon : public AActor
{
	GENERATED_BODY()

protected:
	UPROPERTY(VisibleDefaultsOnly)
	TObjectPtr<USceneComponent> Scene;

	UPROPERTY(VisibleDefaultsOnly)
	TObjectPtr<USkeletalMeshComponent> Body;

	UPROPERTY(VisibleDefaultsOnly)
	FWeaponAssets Data;

	// 자식 클래스 생성자에서 수동으로 설정
	EWeaponName Name;

public:
	// Sets default values for this actor's properties
	ABaseWeapon();

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

	void LoadData(EWeaponName InName);
	void SetBody();
};

Weapon의 데이터가 정의되어있는 Weapon_Struct_Data를 선언해주고, 사용할 수 있다.

 

나머지는 기본적인 엑터 형태로 정의한다.

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


#include "Actors/Weapons/BaseWeapon.h"
#include "Utility/Helper.h"

// Sets default values
ABaseWeapon::ABaseWeapon()
{
	Scene = Helper::CreateSceneComponent<USceneComponent>(this, "Scene");
	Body = Helper::CreateSceneComponent<USkeletalMeshComponent>(this, "Body");
}

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

void ABaseWeapon::LoadData(EWeaponName InName)
{
	const UDataTable* Assets = Helper::GetAsset<UDataTable>("/Script/Engine.DataTable'/Game/Weapons/1_BluePrints/WeaponAssets.WeaponAssets'");

	if (Assets)
	{
		const int32 Value = static_cast<int32>(InName);
		const FName RowName = FName(FString::FromInt(Value));
		Data = *Assets->FindRow<FWeaponAssets>(RowName, "");
	}
}

void ABaseWeapon::SetBody()
{
	Body->SetSkeletalMesh(Data.WeaponMesh);
}

 

LoadData함수의 호출로 객체의 이름을 가져오면, 해당 이름을 기준으로 Struct를 참고하여 값을 불러오고, SetBody()나 지금은 만들지 않았지만, SetMaterial을 통해 값을 쉽게 넣어줄 수 있다.

 

 

728x90