이제 만들어둔 HP바의 부모클래스인 유저 위젯을 상속받는 C++클래스를 만들어주자.

 

이때 블루프린트에서 ProgressBar로 HP바를 정의해뒀는데 이 C++ 클래스에서 똑같은 이름으로 바인딩을 UPROPERTY로 해줄 수 있다.

HealthBar.h

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

#pragma once

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

/**
 * 
 */
UCLASS()
class SLASH_API UHealthBar : public UUserWidget
{
	GENERATED_BODY()
public:
	UPROPERTY(meta = (BindWidget))
	class UProgressBar* HealthBar;
	
};

Enemy클래스에서 블루프린트 객체를 호출하기 위해 부모 객체의 GetUserWidgetObject함수를 사용할 수 있다.

 

이렇게 해주고 블루프린트 상에서 부모클래스를 HealthBar로 바꿔주자.

 

이제 코드상에서 이 위젯을 호출하고 ProgressBar의 속성을 변경할 수 있게 하자.

일단 퍼센트에 따라 체력바가 조정되게 해야한다. 이때 UWidgetComponent에서 자신의 유저 위젯을 반환해주는 함수를

사용해서 현재 사용자 위젯을 가져올 수 있다. 이때 이 함수는 UUserWidget을 반환해주데 우리가 필요한 것은 HealthBar이기 때문에 캐스팅을 해주어야한다.

 

이때 캐스팅이 여러번 이루어지지 않도록 멤버변수를 활용해주자. 그리고 UPROPERTY를 활용해서 기본값에 가비지 값이 할당되지 않도록 하자.

 

HealthBarComponent.h

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

#pragma once

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

/**
 * 
 */
UCLASS()
class SLASH_API UHealthBarComponent : public UWidgetComponent
{
	GENERATED_BODY()

public:
	void SetHealthPercent(float Percent);

private:
	UPROPERTY()
	class UHealthBar* HealthBarWidget;
};

 

HealthBarComponent.cpp

void UHealthBarComponent::SetHealthPercent(float Percent)
{
	if (HealthBarWidget == nullptr)
	{
		HealthBarWidget = Cast<UHealthBar>(GetUserWidgetObject());
	}
	
	if (HealthBarWidget && HealthBarWidget->HealthBar)
	{
		HealthBarWidget->HealthBar->SetPercent(Percent);
	}
}

 

이렇게 유저위젯관련 코드를 작성해주었으니 Enemy 클래스에서 멤버변수의 타입도 바꿔주고 생성자에서 CreateDefaultSubObject의 클래스명을 바꿔주고 BeginPlay에서 이를 호출하여 테스트해보자.

Enemy.h

private:

	UPROPERTY(VisibleAnywhere)
	class UHealthBarComponent* HealthBarWidget;

 

Enemy.cpp

AEnemy::AEnemy()
{
	PrimaryActorTick.bCanEverTick = true;

	GetMesh()->SetCollisionObjectType(ECollisionChannel::ECC_WorldDynamic);
	GetMesh()->SetCollisionResponseToChannel(ECollisionChannel::ECC_Visibility, ECollisionResponse::ECR_Block);
	GetMesh()->SetCollisionResponseToChannel(ECollisionChannel::ECC_Camera, ECollisionResponse::ECR_Ignore);
	GetMesh()->SetGenerateOverlapEvents(true);
	GetCapsuleComponent()->SetCollisionResponseToChannel(ECollisionChannel::ECC_Camera, ECollisionResponse::ECR_Ignore);

	Attributes = CreateDefaultSubobject<UAttributeComponent>(TEXT("Attributes"));
	HealthBarWidget = CreateDefaultSubobject<UHealthBarComponent>(TEXT("HealthBar"));
	HealthBarWidget->SetupAttachment(GetRootComponent());
}

void AEnemy::BeginPlay()
{
	Super::BeginPlay();
	
	if (HealthBarWidget)
	{
		HealthBarWidget->SetHealthPercent(.1f);
	}
}

 

정상적으로 작동하는 것을 볼 수 있다.

'게임공부 > Unreal Engine' 카테고리의 다른 글

[Unreal Engine][C++]22. Death  (1) 2025.01.26
[Unreal Engine][C++]21. Damage  (1) 2025.01.21
[Unreal Engine][C++]19. Actor Component  (0) 2025.01.14
[Unreal Engine][C++]18. Treasure2  (0) 2025.01.03
[Unreal Engine][C++]17. Treasure  (0) 2025.01.03

+ Recent posts