본문 바로가기
포트폴리오 제작

Project_P HUD 위젯 제작

by k99812 2024. 12. 18.

HUD와 기존 위젯 컴포넌트의 차이점


 

위젯 컴포넌트를 통해 생성한 몬스터 HPBar는 GetOwningPlayerPawn함수를 통해 UI를 소유하고 있는

폰을 가져오려면 위 스크린샷과 같이 에러가 발생한다. 그래서 위젯 컴포넌트에서 위젯이 초기화 될때
위젯에 오너를 넘겨 오너를 사용해야 된다.

 

HUD위젯은 플레이어 컨트롤러에 생성을 한다. 그래서 문제없이 GetOwningPlayerPawn 함수를
사용할 수 있다

 

 

위젯 제작


C++ 클래스 생성

 

UserWidget을 상속받아 PPPLayerStatBarUserWidget, PPHUDWidget을 생성한다

 

위젯 블루프린트 생성

 

PPPLayerStatBarUserWidget을 상속받아 위젯 블루프린트를 생성하여 HPBar, MPBar를 프로그래스바와 텍스트를 이용하여 생성한다

 

 

PPHUDWidget을 상속받은 위젯 블루프린트를 생성한다

HUD는 캔버스 패널을 추가한 다음 Palette→User Created에서 생성한 PPPLayerStatBarUserWidget을 캔버스에 적절한 위치에 넣는다

 

UPPPlayerStatBarUserWidget 


헤더파일

#include "CoreMinimal.h"
#include "UI/PPGASUserWidget.h"
#include "GameplayEffectTypes.h"
#include "PPPlayerStatBarUserWidget.generated.h"

/**
 * 
 */
UCLASS()
class PROJECT_P_API UPPPlayerStatBarUserWidget : public UUserWidget
{
	GENERATED_BODY()

public:
	UPPPlayerStatBarUserWidget(const FObjectInitializer& ObjectInitializer);

protected:
	virtual void NativeConstruct() override;

	void OnHealthAttributeChange(const FOnAttributeChangeData& ChangeData);
	void OnMaxHealthAttributeChange(const FOnAttributeChangeData& ChangeData);

	void OnManaAttributeChange(const FOnAttributeChangeData& ChangeData);
	void OnMaxManaAttributeChange(const FOnAttributeChangeData& ChangeData);

	void UpdateHpBar();
	void UpdateMpBar();

	UPROPERTY(meta = (BindWidget))
	TObjectPtr<class UProgressBar> PbHpBar;

	UPROPERTY(meta = (BindWidget))
	TObjectPtr<class UProgressBar> PbMpBar;

	UPROPERTY(meta = (BindWidget))
	TObjectPtr<class UTextBlock> TxtHpStat;

	UPROPERTY(meta = (BindWidget))
	TObjectPtr<class UTextBlock> TxtMpStat;

private:
	float CurrentHealth = 0.0f;
	float CurrentMaxHealth = 0.0f;

	float CurrentMana = 0.0f;
	float CurrentMaxMana = 0.0f;
};

 

  • UPPPlayerStatBarUserWidget(const FObjectInitializer& ObjectInitializer);
    • 위젯 클래스의 생성자
    • 위젯 클래스는 기본 생성자가 없고 FObjectInitializer를 매개변수로 하는 생성자만 존재
  • virtual void NativeConstruct() override;
    • 위젯이 AddToViewport 함수가 실행되면 호출되는 함수
  • void OnHealthAttributeChange(const FOnAttributeChangeData& ChangeData);
    void OnMaxHealthAttributeChange(const FOnAttributeChangeData& ChangeData);
    • HP, MP 어트리뷰트가 바뀔때 실행되는 델리게이트에 연결할 콜백함수들
  • void UpdateHpBar();
    void UpdateMpBar();
    • HP, MP가 변경되면 실행할 함수들
  • UPROPERTY(meta = (BindWidget))
    TObjectPtr<class UProgressBar> PbHpBar;

    UPROPERTY(meta = (BindWidget))
    TObjectPtr<class UTextBlock> TxtHpStat;

    • UPROPERTY(meta = (BindWidget)) 설정으로 블루프린트 위젯 변수명이랑 동일하게 변수명을 설정하면 자동으로 위젯을 바인드 해줌

 

생성자

UPPPlayerStatBarUserWidget::UPPPlayerStatBarUserWidget(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{

}

 

위젯 생성자는 Super()로 매개변수를 부모한테 넘겨줘야 함

 

NativeConstruct

void UPPPlayerStatBarUserWidget::NativeConstruct()
{
	UAbilitySystemComponent* ASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(GetOwningPlayerPawn());

	if (ASC)
	{
		ASC->GetGameplayAttributeValueChangeDelegate(UPPCharacterAttributeSet::GetHealthAttribute()).
			AddUObject(this, &UPPPlayerStatBarUserWidget::OnHealthAttributeChange);
		ASC->GetGameplayAttributeValueChangeDelegate(UPPCharacterAttributeSet::GetMaxHealthAttribute()).
			AddUObject(this, &UPPPlayerStatBarUserWidget::OnMaxHealthAttributeChange);

		ASC->GetGameplayAttributeValueChangeDelegate(UPPCharacterAttributeSet::GetManaAttribute()).
			AddUObject(this, &UPPPlayerStatBarUserWidget::OnManaAttributeChange);
		ASC->GetGameplayAttributeValueChangeDelegate(UPPCharacterAttributeSet::GetMaxManaAttribute()).
			AddUObject(this, &UPPPlayerStatBarUserWidget::OnMaxManaAttributeChange);

		const UPPCharacterAttributeSet* AttributeSet = ASC->GetSet<UPPCharacterAttributeSet>();
		if (AttributeSet)
		{
			CurrentHealth = AttributeSet->GetHealth();
			CurrentMaxHealth = AttributeSet->GetMaxHealth();

			if (CurrentMaxHealth > 0.0f)
			{
				UpdateHpBar();
			}

			CurrentMana = AttributeSet->GetMana();
			CurrentMaxMana = AttributeSet->GetMaxMana();

			if (CurrentMaxMana > 0.0f)
			{
				UpdateMpBar();
			}
		}
	}
}

 

  • UAbilitySystemComponent* ASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(GetOwningPlayerPawn());
    • GetOwningPlayerPawn 함수로 위젯을 소유하고있는 폰을 가져와 ASC를 가져옴
  • ASC->GetGameplayAttributeValueChangeDelegate(UPPCharacterAttributeSet::GetHealthAttribute()).
    AddUObject(this, &UPPPlayerStatBarUserWidget::OnHealthAttributeChange);
    • 어트리뷰트셋을 사용하고 있으면 ASC에서 어트리뷰트가 바뀔때마다 호출되는 델리게이트를 지원해줌
    • 콜백함수를 연결
  • const UPPCharacterAttributeSet* AttributeSet = ASC->GetSet<UPPCharacterAttributeSet>();
    • ASC를 이용해 어트리뷰트셋을 가져옴
  • CurrentHealth = AttributeSet->GetHealth();
    CurrentMaxHealth = AttributeSet->GetMaxHealth();
    • 어트리뷰트셋에서 스탯을 가져옴
  • if (CurrentMaxHealth > 0.0f)
    {
    UpdateHpBar();
    }
    • 스텟을 잘가져왔으면 UpdateHpBar로 UI에 반영

 

OnHealthAttributeChange

void UPPPlayerStatBarUserWidget::OnHealthAttributeChange(const FOnAttributeChangeData& ChangeData)
{
	CurrentHealth = ChangeData.NewValue;
	UpdateHpBar();
}

 

  • CurrentHealth = ChangeData.NewValue;
    • ChangeData로 바뀐 어트리뷰트 값을 반영
  • UpdateHpBar();
    • UI 업데이트
  • 다른 어트리뷰트들도 이와같이 함수를 작성

 

UpdateHpBar

void UPPPlayerStatBarUserWidget::UpdateHpBar()
{
	if (PbHpBar)
	{
		PbHpBar->SetPercent(CurrentHealth / CurrentMaxHealth);
	}
	
	if (TxtHpStat)
	{
		TxtHpStat->SetText(FText::FromString(FString::Printf(TEXT("%.0f/%0.f"), CurrentHealth, CurrentMaxHealth)));
	}
}

 

변경된 값들을 프로그래스 바와 텍스트에 적용

 

UPPHUDWidget


헤더파일

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

/**
 * 
 */
UCLASS()
class PROJECT_P_API UPPHUDWidget : public UUserWidget
{
	GENERATED_BODY()
	
public:
	UPPHUDWidget(const FObjectInitializer& ObjectInitializer);

protected:
	virtual void NativeConstruct() override;

	UPROPERTY(meta = (BindWidget))
	TObjectPtr<class UPPPlayerStatBarUserWidget> PlayerStatBar;
};

 

  • UPROPERTY(meta = (BindWidget))
    TObjectPtr<class UPPPlayerStatBarUserWidget> PlayerStatBar;
    • 블루프린트에서 생성한 위젯을 변수로 생성 및 바인드

HUDWidget에서는 하위 위젯에서 기능을 구현하여 별도로 구현할 필요가 없음