언리얼 5

230921 인벤토리 설비 및 아이템 설비

슬뷔 2023. 9. 21. 11:02

인벤토리 설비 및 아이템 설비

처음 게임을 켰을 때, 인벤토리창 안보이게 설정

void UMainHUD_Base::NativeConstruct()
{
	Super::NativeConstruct();
    
	m_Inventory = Cast<UInventory_Base>(GetWidgetFromName(FName("Inventory")));
	if (!IsValid(m_Inventory))
	{
		LOG(LogTemp, Error, TEXT("Inventory 위젯 못 찾음"));
	}
	else
	{
		m_Inventory->SetVisibility(ESlateVisibility::Hidden);
	}
}

게임인스턴스랑 연동해서 게임모드를 가지고 있을 것

GameInstance_Base

#include "CoreMinimal.h"
#include "Engine/GameInstance.h"
#include "Effect/EffectMgr.h"

#include "GameInstance_Base.generated.h"

class UInvenMgr;

UCLASS()
class UNREAL_3TH_API UGameInstance_Base : public UGameInstance
{
	GENERATED_BODY()	
private:
	UInvenMgr*	m_InvenMgr;

public:
	UGameInstance_Base();
	~UGameInstance_Base();

	friend class UInvenMgr;
};
#include "GameInstance_Base.h"
#include "Manager/InvenMgr.h"


UGameInstance_Base::UGameInstance_Base()
	: m_InvenMgr(nullptr)
{
	ConstructorHelpers::FObjectFinder<UDataTable> tablefinder(TEXT("/Script/Engine.DataTable'/Game/BlueprintClass/Item/DT_GameItem.DT_GameItem'"));
	if (tablefinder.Succeeded())
	{
		UInvenMgr::GetInst(this)->SetGameItemDataTable(tablefinder.Object);
	}
	else
	{
		LOG(LogTemp, Error, TEXT("게임 아이템 데이터 테이블 못 찾음"));
	}
}

UGameInstance_Base::~UGameInstance_Base()
{
}

enum.h 에 ITEM_ID 와 ITEM_TYPE 설계

UENUM(BlueprintType)
enum class EITEM_ID : uint8
{
	CI_POTION,
	CI_MEGAPOTION,

	EW_LONGSWORD,
	EW_DAGGER,
	EW_BOW,

	EA_LEATHER_ARMOR,
	EA_STEEL_ARMOR,
	EA_PLATINUM_ARMOR
};

UENUM(BlueprintType)
enum class EITEM_TYPE : uint8
{
	WEAPON,
	ARMOR,
	ACCESSORY,
	CONSUMABLE
};

struct.h 에 아이템 구조체 설계 ( GameItemInfo )

// 아이템 구조체
USTRUCT(Atomic, BlueprintType)
struct FGameItemInfo
	: public FTableRowBase
{
	GENERATED_BODY();

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	EITEM_ID		ID;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	EITEM_TYPE		TYPE;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FString			Description;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FString			IconPath;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float			Att;
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float			Def;
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float			Heal_HP;
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float			Heal_MP;
};

UObject를 상속받은 InvenMgr 생성 ( 싱글톤으로 제작 )

#include "../Header/global.h"

#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "InvenMgr.generated.h"

USTRUCT()
struct FItemStack
{
	GENERATED_BODY()

	FGameItemInfo*	ItemInfo;
	int32			Stack;
};

UCLASS()
class UNREAL_3TH_API UInvenMgr : public UObject
{
	GENERATED_BODY()

private:
	static UWorld* m_World;

private:
	// 아이템 데이터 테이블
	UDataTable*						m_ItemTable;
	TMap<EITEM_ID, FGameItemInfo>	m_mapItemInfo;

	// 실제 플레이어가 보유한 아이템 정보
	TMap< EITEM_ID, FItemStack>		m_BackPack[(int32)EITEM_TYPE::END];
	

	
public:
	static UInvenMgr* GetInst(UWorld* _World);
	static UInvenMgr* GetInst(UGameInstance* _GameInst);
	void SetGameItemDataTable(UDataTable* _ItemDataTable);
	void AddGameItem(EITEM_ID _ID);

	void OpenInventoryUI();
};
#include "InvenMgr.h"
#include "../GameInstance_Base.h"

#include "../Unreal_3thGameModeBase.h"
#include "../UI/MainHUD_Base.h"
#include "../UI/Inventory_Base.h"

#include "../System/InvenItemData.h"


UWorld* UInvenMgr::m_World = nullptr;

UInvenMgr* UInvenMgr::GetInst(UWorld* _World)
{
	m_World = _World;

	return GetInst(m_World->GetGameInstance());
}

UInvenMgr* UInvenMgr::GetInst(UGameInstance* _GameInst)
{
	UGameInstance_Base* pGameInst = Cast<UGameInstance_Base>(_GameInst);

	if (!IsValid(pGameInst->m_InvenMgr))
	{
		pGameInst->m_InvenMgr = NewObject<UInvenMgr>();
		pGameInst->m_InvenMgr->AddToRoot();
	}

	return pGameInst->m_InvenMgr;
}

void UInvenMgr::SetGameItemDataTable(UDataTable* _ItemDataTable)
{
	m_ItemTable = _ItemDataTable;

	// 데이터 테이블 안에있는 모든 정보를 TArray 에 넣는다.
	FString str;
	TArray<FGameItemInfo*>	arrTableData;
	m_ItemTable->GetAllRows<FGameItemInfo>(str, arrTableData);

	// 테이블 안에 있는 아이템 정보를 아이템 ID 를 Key 로 하는 TMap 에 넣는다.
	for (int32 i = 0; i < arrTableData.Num(); ++i)
	{
		m_mapItemInfo.Add(arrTableData[i]->ID, *arrTableData[i]);
	}	
}

void UInvenMgr::AddGameItem(EITEM_ID _ID)
{
	// 습득한 아이템 아이디에 해당하는 아이템 정보를 가져온다
	FGameItemInfo* pItemInfo = m_mapItemInfo.Find(_ID);

	if (nullptr == pItemInfo)
	{
		LOG(LogTemp, Error, TEXT("ITEM ID에 해당하는 아이템 정보를 찾을 수 없음"));
		return;
	}

	// 아이템 타입에 맞는 백팩에 접근 후, 해당 아이템을 이미 보유하고 있는지 확인한다
	FItemStack* pItemStack = m_BackPack[(int32)pItemInfo->TYPE].Find(_ID);


	if (nullptr == pItemStack)
	{
		m_BackPack[(int32)pItemInfo->TYPE].Add(_ID, FItemStack{ pItemInfo, 1 });
	}
	// 이미 가지고 있다면,
	else
	{
		++pItemStack->Stack;
	}

}

void UInvenMgr::OpenInventoryUI()
{
	// 현재 게임모드를 체크
	AUnreal_3thGameModeBase* pGameMode = Cast<AUnreal_3thGameModeBase>(UGameplayStatics::GetGameMode(m_World));
	if (!IsValid(pGameMode))
		return;

	// 게임모드로부터 메인 HUD 가져오기
	UMainHUD_Base* MainHUD = pGameMode->GetMainHUD();
	MainHUD->ShowInventoryUI(true);

	// MainHUD 로부터 InventoryWidget(UI) 가져오기
	UInventory_Base* InventoryWidget = MainHUD->GetInventoryWidget();

	// InventoryWidget(UI) 이전 내용 클리어하기
	InventoryWidget->Clear();

	// InvenMgr 가 보유하고 있는 아이템 목록을 전부 UI로 보내기
	for (int32 i = 0; (int32)EITEM_TYPE::END; ++i)
	{
		for (auto Iterator = m_BackPack[i].CreateConstIterator(); Iterator; ++Iterator)
		{
			UInvenItemData* pData = NewObject<UInvenItemData>();
			pData->SetIconImgPath(Iterator.Value().ItemInfo->IconPath);
			pData->SetItemName(Iterator.Value().ItemInfo->Description);
			pData->SetItemCount(Iterator.Value().Stack);

			InventoryWidget->AddItem(pData);
		}
	}
}

블루프린트 DT_GameItem 생성 ( 기타 -> 데이터 테이블 -> GameItemInfo)

 

아이템 생성 BPC_Item

스태틱 매쉬추가

 

변수 -> ItemID 추가 + 공개처리

 

Inventory_Base 기능 추가

UCLASS()
class UNREAL_3TH_API UInventory_Base : public UUserWidget
{
	GENERATED_BODY()

public:
	void AddItem(UObject* _ItemData);
	void Clear();
};
void UInventory_Base::AddItem(UObject* _ItemData)
{
	m_ListView->AddItem(_ItemData);
}

void UInventory_Base::Clear()
{
	m_ListView->ClearListItems();
}

MainHUD_Base 기능 추가

class UNREAL_3TH_API UMainHUD_Base : public UUserWidget
{
	GENERATED_BODY()

public:
	void ShowInventoryUI(bool _bShow);
}
void UMainHUD_Base::ShowInventoryUI(bool _bShow)
{
	if (_bShow)
	{
		m_Inventory->SetVisibility(ESlateVisibility::Hidden);
	}
	else
	{
		m_Inventory->SetVisibility(ESlateVisibility::Visible);
	}
}

Character_Base 기능 추가

UCLASS()
class UNREAL_3TH_API ACharacter_Base : public ACharacter
{
	GENERATED_BODY()
private:
	void OnInventory(const FInputActionInstance& _Instance);
}
void ACharacter_Base::JumpAction(const FInputActionInstance& _Instance)
{
	Super::Jump();

	// 점프하면 소형 포션 습득
	UInvenMgr::GetInst(GetWorld())->AddGameItem(EITEM_ID::CI_POTION);
}

void ACharacter_Base::OnInventory(const FInputActionInstance& _Instance)
{
	UInvenMgr::GetInst(GetWorld())->OpenInventoryUI();
}