언리얼 5

230920 몬스터 체력바 / 인벤토리

슬뷔 2023. 9. 20. 11:05

몬스터 체력바 ( 머리 위에 띄우는 위젯 )

BlueprintClass -> UMG -> Monster -> MonsterInfo

 

MonsterInfo ( 유저인터페이스 -> 위젯블루프린트 ) 생성

스케일박스 -> 크기박스 -> 캔버스패널 -> 보더 -> ProgressBar -> 텍스트

크기박스 Custom 200 * 100

보더 : 앵커 정중앙 / x위치 0, y위치 30 /정렬 0.5, 0.5 / 크기 200, 20

ProgressBar : 앵커 정중앙 / x위치 0, y위치 30 /정렬 0.5, 0.5 / 크기 195, 18

텍스트 : 앵커 정중앙 / x위치 0, y위치 -10 /정렬 0.5, 0.5 / 크기 169, 40 / 양쪽맞춤 가운데

C++ 에서 위젯 사용하기 위해서 Monster_Base 에 기능 추가

class UNREAL_3TH_API AMonster_Base : public ACharacter
{
	GENERATED_BODY()
private:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Info", meta = (RowType = "MonInfo", AllowPrivateAccess = "true"))
	class UWidgetComponent* m_WidgetComponent;
}
AMonster_Base::AMonster_Base()
{
	// 위젯을 보여주는 컴포넌트 추가
	m_WidgetComponent = CreateDefaultSubobject<UWidgetComponent>(L"WidgetComponent");
	m_WidgetComponent->SetupAttachment(GetCapsuleComponent());
}

UUserWidget 상속 받은 MonsterInfo_Base 생성

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "MonsterInfo_Base.generated.h"

UCLASS()
class UNREAL_3TH_API UMonsterInfo_Base : public UUserWidget
{
	GENERATED_BODY()
private:
	class UTextBlock*	m_Name;
	class UProgressBar* 	m_HPBar;

public:
	void SetHPRatio(float _Ratio);
	void SetTextBlock(const FString& _name);

public:
	virtual void NativeConstruct() override;
	virtual void NativeTick(const FGeometry& _geo, float _DT) override;
};
#include "MonsterInfo_Base.h"

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

#include "Components/TextBlock.h"
#include "Components/ProgressBar.h"

void UMonsterInfo_Base::NativeConstruct()
{
	Super::NativeConstruct();

	m_Name = Cast<UTextBlock>(GetWidgetFromName(TEXT("Name")));
	m_HPBar = Cast<UProgressBar>(GetWidgetFromName(TEXT("HPBar")));

	if (!IsValid(m_Name) || !IsValid(m_HPBar))
	{
		LOG(LogTemp, Error, TEXT("Widget 못 찾음"));
	}
}

void UMonsterInfo_Base::NativeTick(const FGeometry& _geo, float _DT)
{
	Super::NativeTick(_geo, _DT);
}

void UMonsterInfo_Base::SetHPRatio(float _Ratio)
{
	if (IsValid(m_HPBar))
	{
		m_HPBar->SetPercent(_Ratio);
	}
}

void UMonsterInfo_Base::SetTextBlock(const FString& _name)
{
	if (IsValid(m_HPBar))
	{
		m_Name->SetText(FText::FromString(_name));
	}
}

Monster_Base BeginPlay 에 몬스터 위젯 설정

*  그냥 GetWidget 하면 userwidget 이 나오기 때문에 원하는 함수?로 다운 캐스팅을 해주어야한다

void AMonster_Base::BeginPlay()
{
	Super::BeginPlay();		

	// 위젯에 이름 및 체력 퍼센트 설정
	UMonsterInfo_Base* pMonInfoWidget = Cast<UMonsterInfo_Base>(m_WidgetComponent->GetWidget());
	if (!IsValid(pMonInfoWidget))
	{
		LOG(Monster, Error, TEXT("몬스터 위젯이 올바르지 않음"));
	}
	else
	{
		pMonInfoWidget->SetTextBlock("오크");
		pMonInfoWidget->SetHPRatio(0.5f);
	}

}

Material 에서 양방향 설정

-> 기본으로 Cull_Back 인데, 체력바는 뒤로 간다고 안그려지거나 그러면 안돼서.. 

 

몬스터인포 설정할 때 monsterinfo_base 의 nativeconstruct가 늦게 호출되어서, monster_base의 beginplay 에서 호출문제가 있다. (최초의 초기화 시점에서)

 

해결방안

-> 미리 값을 넣어주고, 그걸 호출한다

class UNREAL_3TH_API UMonsterInfo_Base : public UUserWidget
{
	GENERATED_BODY()
private:
	FText m_NameSet;
	float m_HPRatio;
}
void UMonsterInfo_Base::NativeConstruct()
{
	Super::NativeConstruct();

	m_Name = Cast<UTextBlock>(GetWidgetFromName(TEXT("Name")));
	m_HPBar = Cast<UProgressBar>(GetWidgetFromName(TEXT("HPBar")));

	if (!IsValid(m_Name) || !IsValid(m_HPBar))
	{
		LOG(LogTemp, Error, TEXT("Widget 못 찾음"));
	}
	else
	{
		m_Name->SetText(m_NameSet);
		m_HPBar->SetPercent(m_HPRatio);
	}
}

void UMonsterInfo_Base::SetHPRatio(float _Ratio)
{
	m_HPRatio = _Ratio;

	if (IsValid(m_HPBar))
	{
		m_HPBar->SetPercent(m_HPRatio);
	}
}

void UMonsterInfo_Base::SetTextBlock(const FString& _name)
{
	m_NameSet = FText::FromString(_name);

	if (IsValid(m_Name))
	{
		m_Name->SetText(m_NameSet);
	}
}

 

인벤토리

BlueprintClass -> UMG -> Inventory-> Inventory

Inventory ( 유저인터페이스 -> 위젯블루프린트 ) 생성

리스트엔트리

반드시 엔트리 위젯클래스를 설정해주어야한다

* 엔트리 위젯클래스 -> 자료형을 알려달라는 의미


BlueprintClass -> UMG -> Inventory-> InvenItem 생성

InvenItem ( 유저인터페이스 -> 위젯블루프린트 ) 생성

InvenItem  -> 리스트의 한 항목

그래프->클래스세팅->디테일->구현된 인터페이스-> UserObjectListEntry


이 작업을 하면, 리스트 엔트리에서 엔트리 위젯 클래스로 InvenItem 선택 가능해진다.

UUserWidget 상속 받은 Inventory_Base 생성

 

UUserWidget 상속 받은 InvenItem_Base 생성

* 리스트 뷰에 넣을 item 은 uobject* 로 가리키면서 받는다.

 

UObject 를 상속받은 InvenItemData 생성

MainHUD에 Inventory 생성

class UNREAL_3TH_API UMainHUD_Base : public UUserWidget
{
	GENERATED_BODY()
	
private:
	UInventory_Base*	m_Inventory;
}
void UMainHUD_Base::NativeConstruct()
{
	Super::NativeConstruct();
    
	m_Inventory = Cast<UInventory_Base>(GetWidgetFromName(FName("Inventory")));
	if (!IsValid(m_Inventory))
	{
		LOG(LogTemp, Error, TEXT("Inventory 못 찾음"));
	}
}