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

Project_P 체력바 UI 생성

by k99812 2024. 10. 21.

위젯을 담을 위젯 컴포넌트 생성


 

UWidgetComponent를 상속받아 PPGASWidgetComponent 생성

 

UWidgetComponent 헤더파일


#include "CoreMinimal.h"
#include "Components/WidgetComponent.h"
#include "PPGASWidgetComponent.generated.h"

/**
 * 
 */
UCLASS()
class PROJECT_P_API UPPGASWidgetComponent : public UWidgetComponent
{
	GENERATED_BODY()
	
protected:
	virtual void InitWidget() override;
};

 

  • virtual void InitWidget() override;
    • 위젯의 설정을 위해  InitWidget 함수 오버라이드

 

Cpp 파일


InitWidget

void UPPGASWidgetComponent::InitWidget()
{
	Super::InitWidget();

	UPPGASUserWidget* GASUserWidget = Cast<UPPGASUserWidget>(GetWidget());
	if (GASUserWidget)
	{
		GASUserWidget->SetAbilitySystemComponent(GetOwner());
	}
}

 

  • #include "UI/PPGASUserWidget.h" 추가
  • Super::InitWidget(); 
    • 부모로직 실행
  • UPPGASUserWidget* GASUserWidget = Cast<UPPGASUserWidget>(GetWidget());
    • 위젯 설정을 위해 GetWidget 함수로 위젯을 가져옴
  • GASUserWidget->SetAbilitySystemComponent(GetOwner());
    • GASUserWidget 의 SetAbilitySystemComponent를 호출하여 ASC를 초기화
    • SetAbilitySystemComponent는 GASUserWidget에서 생성한 함수

 

UserWidget 생성


 

  • UserWidget을 상속받아 ASC를 가지고 있을 PPGASUserWidget을 생성
  • PPGASUserWidget을 상속받아 PPGASHpBarUserWidget 생성

 

PPGASUserWidget 헤더파일


#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "AbilitySystemInterface.h"
#include "PPGASUserWidget.generated.h"

/**
 * 
 */
UCLASS()
class PROJECT_P_API UPPGASUserWidget : public UUserWidget, public IAbilitySystemInterface
{
	GENERATED_BODY()
	
public:
	virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override;

	virtual void SetAbilitySystemComponent(AActor* Owner);

protected:
	UPROPERTY(EditAnywhere, Category = "GAS")
	TObjectPtr<class UAbilitySystemComponent> ASC;
};

 

  • virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override;
    • ASC를 가지고있으면 인터페이스를 상속받아 구현해야할 함수
  • virtual void SetAbilitySystemComponent(AActor* Owner);
    • 위젯 컴포넌트에서 위젯이 생성될때 해당 함수를 호출하여 매개변수로 오너를 받아 오너의 ASC를 가져옴
    • 자식 클래스에서 추가적인 로직을 위해 virtual 함수로 구현
  • TObjectPtr<class UAbilitySystemComponent> ASC;
    • ASC를 저장할 변수

 

Cpp파일


GetAbilitySystemComponent

UAbilitySystemComponent* UPPGASUserWidget::GetAbilitySystemComponent() const
{
    return ASC;
}

 

  • ASC를 return해줌

 

SetAbilitySystemComponent

void UPPGASUserWidget::SetAbilitySystemComponent(AActor* Owner)
{
    if (IsValid(Owner))
    {
        ASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(Owner);
    }
}

 

  • 매개변수로 오너액터를 받아 UAbilitySystemBlueprintLibrary의 GetAbilitySystemComponent 함수를 이용하여 오너의 ASC를 가져옴

 

PPGASHpBarUserWidget 헤더파일


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

/**
 * 
 */
UCLASS()
class PROJECT_P_API UPPGASHpBarUserWidget : public UPPGASUserWidget
{
	GENERATED_BODY()

protected:
	virtual void SetAbilitySystemComponent(AActor* Owner) override;

	//#include "GameplayEffectTypes.h"추가
	void OnHealthAttributeChange(const FOnAttributeChangeData& ChangeData);
	void OnMaxHealthAttributeChange(const FOnAttributeChangeData& ChangeData);

	void UpdateHpBar();

	//meta = (BindWidget) 설정시 동일한 이름을 가진 위젯을 찾아 엔진이 초기화 해줌
	UPROPERTY(meta = (BindWidget))
	TObjectPtr<class UProgressBar> PbHpBar;

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

	float CurrentHealth = 0.0f;
	float CurrentMaxHealth = 0.1f;
};

 

  • virtual void SetAbilitySystemComponent(AActor* Owner) override;
    • 부모클래스의 SetAbilitySystemComponent 함수를 상속받아 추가적인 로직 구현
  • void OnHealthAttributeChange(const FOnAttributeChangeData& ChangeData);
    void OnMaxHealthAttributeChange(const FOnAttributeChangeData& ChangeData);
    • FOnAttributeChangeData를 사용하기 위해 #include "GameplayEffectTypes.h"추가
    • 해당 함수들은 ASC의 어트리뷰트가 바뀔때 호출되는 델리게이트에 연결할 콜백함수들
  • void UpdateHpBar();
    • 위젯의 프로그래스 바와 텍스트를 바꿀 함수
  • UPROPERTY(meta = (BindWidget))
    TObjectPtr<class UProgressBar> PbHpBar;

    UPROPERTY(meta = (BindWidget))
    TObjectPtr<class UTextBlock> TxtHpStat;
    • 프로그래스 바와, 텍스트를 저장할 변수
    • meta = (BindWidget) 설정시 동일한 이름을 가진 위젯을 찾아 엔진이 초기화 해줌
  • float CurrentHealth = 0.0f;
    float CurrentMaxHealth = 0.1f;
    • 체력, 최대체력을 저장할 변수

 

Cpp 파일


SetAbilitySystemComponent

void UPPGASHpBarUserWidget::SetAbilitySystemComponent(AActor* Owner)
{
	Super::SetAbilitySystemComponent(Owner);

	if (ASC)
	{
		//특정 어트리뷰트값이 바뀔때 마다 호출되는 델리게이트
		ASC->GetGameplayAttributeValueChangeDelegate(UPPCharacterAttributeSet::GetHealthAttribute()).AddUObject(this, &UPPGASHpBarUserWidget::OnHealthAttributeChange);
		ASC->GetGameplayAttributeValueChangeDelegate(UPPCharacterAttributeSet::GetMaxHealthAttribute()).AddUObject(this, &UPPGASHpBarUserWidget::OnMaxHealthAttributeChange);
	
		const UPPCharacterAttributeSet* CurrentAttributeSet = ASC->GetSet<UPPCharacterAttributeSet>();
		if (CurrentAttributeSet)
		{
			CurrentHealth = CurrentAttributeSet->GetHealth();
			CurrentMaxHealth = CurrentAttributeSet->GetMaxHealth();
			if (CurrentMaxHealth > 0.0f)
			{
				UpdateHpBar();
			}
		}
	}
}

 

  • Super::SetAbilitySystemComponent(Owner);
    • 부모로직 실행
  • ASC->GetGameplayAttributeValueChangeDelegate(~~~);
    • GetGameplayAttributeValueChangeDelegate 함수로 체력, 최대체력 어트리뷰트가 바뀔때마다 호출되는 델리게이트에 콜백함수 연결
  • const UPPCharacterAttributeSet* CurrentAttributeSet = ASC->GetSet<UPPCharacterAttributeSet>();
    • ASC의 GetSet함수로 어트리뷰트셋을 가져옴
    • CurrentHealth = CurrentAttributeSet->GetHealth();
      CurrentMaxHealth = CurrentAttributeSet->GetMaxHealth();
      • 가져온 어트리뷰트로 체력, 최대체력 변수를 초기화
    • UpdateHpBar();
      • 초기화한 변수들로 초기 체력바 업데이트

 

OnHealthAttributeChange, OnMaxHealthAttributeChange

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

void UPPGASHpBarUserWidget::OnMaxHealthAttributeChange(const FOnAttributeChangeData& ChangeData)
{
	CurrentMaxHealth = ChangeData.NewValue;
	UpdateHpBar();
}

 

  • ChangeData로 변경된 어트리뷰트 값이 들어옴
  • CurrentHealth = ChangeData.NewValue;
    • 변경된 어트리뷰트값으로 변수 업데이트
  • UpdateHpBar();
    • 체력바 업데이트

 

UpdateHpBar

void UPPGASHpBarUserWidget::UpdateHpBar()
{
	if (PbHpBar)
	{
		PbHpBar->SetPercent(CurrentHealth / CurrentMaxHealth);
	}

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

 

  • #include "Components/ProgressBar.h" 추가
    #include "Components/TextBlock.h" 추가
  • PbHpBar->SetPercent(CurrentHealth / CurrentMaxHealth);
    • CurrentHealth / CurrentMaxHealth로 프로그래스바 설정
  • TxtHpStat->SetText(FText::FromString(FString::Printf(TEXT("%.0f/%0.f"), CurrentHealth, CurrentMaxHealth)));
    • 텍스트 설정