Hi everyone. I have HP Progress Bar in the top left corner when the character is attacked. Like the picture.
made Progress Bar with WBP_HpBar and added WBP_HpBar that I made to WBP_HUD. And I wrote the code because I wanted to make HpBar shrink if the character was attacked. Below is the code I wrote.
class LIFEOFLUCK_API IOLHpInterface
{
GENERATED_BODY()
// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:
virtual float SetHp() = 0;
};
#include "Interface/OLAttackInterface.h"
#include "Interface/OLHpInterface.h"
UCLASS()
class LIFEOFLUCK_API AOLCharacterBase : public ACharacter, public IOLAttackInterface, public IOLHpInterface
{
GENERATED_BODY()
// HP
protected:
virtual float SetHp() override;
};
float AOLCharacterBase::SetHp()
{
return Hp / MaxHp;
}
For your information, the AOLCharacterBase has a TakeDamage function, where the Hp value changes (when under attack)
UCLASS()
class LIFEOFLUCK_API UOLHpBarWidget : public UUserWidget
{
GENERATED_BODY()
public:
UOLHpBarWidget(const FObjectInitializer& ObjectInitializer);
protected:
class UProgressBar* HpBar; // HpBar
void UpdateHpBar(); // Hp 프로그레스바 체력에 따라 변경하는 함수
UPROPERTY()
float UpdateHp;
};
#include "UI/OLHpBarWidget.h"
#include "Interface/OLHpInterface.h"
#include "Components/ProgressBar.h"
UOLHpBarWidget::UOLHpBarWidget(const FObjectInitializer& ObjectInitializer) :Super(ObjectInitializer)
{
}
void UOLHpBarWidget::UpdateHpBar()
{
APawn* Player = GetOwningPlayerPawn(); // Player 가져오기
ensure(Player);
IOLHpInterface* PlayerInterface = Cast<IOLHpInterface>(Player);
if (!PlayerInterface)
{
UE_LOG(LogTemp, Error, TEXT("Cast to IOLHpInterface failed!"));
return;
}
UpdateHp = PlayerInterface->SetHp();
UE_LOG(LogTemp, Log, TEXT("UpdateHp: %f"), UpdateHp);
HpBar->SetPercent(UpdateHp);
UE_LOG(LogTemp, Error, TEXT("UpdateHp"));
}
I wrote the code like this. The problem now is that HpBar appears well on the screen. But SetPercent doesn’t seem to work. I don’t think Hp ProgressBar is being updated.
And the logs I wrote in UpdateHpBar don’t come up. I don’t know what the problem is.. (I might have written the wrong code)
I’d really appreciate your help.(Because I used a translator, words can be unnatural. Please understand..)
When I checked the code, I didn’t call the UpdateHpBar function. I just made it
I’m sorry but I didn’t understand this.. Can you say it again? (I’m having a little difficulty understanding it by using a translator. Please understand.)
I modified the code as above. At this time, a log called Noooo HpBar appeared. I don’t think there’s an HpBar.
I think the Hp suddenly went to zero too. The color is gone.
I think it’s correct that the HpBar was not created. And I thought about it, if the character’s Hp is reduced, they should call the UpdateHpBar function somewhere, but they didn’t call it.
The problem with my code seems to be that HpBar has not been created, and Update HpBar is not called anywhere, so it doesn’t seem to diminish when attacked.
I’ve modified the code a little more now. I’ve created HpBar. Can you please check if this is the right way to do it..?
UCLASS()
class LIFEOFLUCK_API UOLHpBarWidget : public UUserWidget
{
GENERATED_BODY()
public:
UOLHpBarWidget(const FObjectInitializer& ObjectInitializer);
protected:
virtual void NativeConstruct() override;
UPROPERTY(EditAnywhere, Category = Hp)
TObjectPtr<class UProgressBar> HpBarProgress; // HpBar
...
};
void UOLHpBarWidget::NativeConstruct()
{
Super::NativeConstruct();
// 해당 컨트롤을 이름으로 찾기
HpBarProgress = Cast<UProgressBar>(GetWidgetFromName(TEXT("HpBar")));
ensure(HpBarProgress);
UpdateHpBar();
}
I modified it like this. I named it HpBar because I set the Progress Bar as HpBar. That’s how I get the UpdateHp log.
Now the problem is UE_LOG ("LogTemp, Log, TEXT (“UpdateHp: %f”), UpdateHp); I think it’s written differently from what I intended. Because the Hp I thought was 1, but that log is outputting 0. I think that’s why Progress Bar appears gray.
I’ll do something about the interface! But thank you very much for your answer
Could you please confirm if my understanding is correct for the reason why I have to make it like the code you wrote? If you don’t mind…!
When you add a Progress Bar in the Unreal Editor and call the UI in code, you must create a real object. To move the Progress Bar (named HpBar) created by the Unreal Editor through setpercent, you must find the appropriate HpBar and put it in the object.
Through TObjectPtr, we create HpBarProgress, a ProgressBar variable, and assign an HpBar widget to it. So if the widget is assigned to HpBarProgress, you can use these functions such as SetPercent with this variable
(At this time, TObjectPtr is because I used HpBar to create a direct element.)
At this time, I would appreciate it if you could think that the interface is just a code from AOLCharacterBase. I think it’s just a function from AOLCharacterBase, ignoring the interface. (I think I confused you because I made it based on lectures from other places.
UOLHpBarWidget::Initialize() is not an interface. It is just a member method in UOLHpBarWidget overriding the inherited method UUserWidget::Initialize()
The declaration below just declares a pointer (an empty address in memory)
UCLASS()
class LIFEOFLUCK_API UOLHpBarWidget : public UUserWidget
. . .
protected:
class UProgressBar* HpBar; // HpBar
. . .
at this point HpBae is nullptr because there is no object in it. This is why if(HpBar)... retunrs false and UE_LOG(LogTemp, Error, TEXT("Nooooo HpBar")); is executed.
The line below creates a progress bar and assigns it to HpBar
Initialize() is executed before the NativeConstruct() I think… You can try moving the code in
NativeConstruct() and say if it shows. As I said, one of my few goals in life is to I avoid doing UI in C++ but I saw that you are missing the construction of the HpBar so I chipped in.
It was supposed to run before NativeConstruct(). Thanks for letting me know!
If you don’t configure the UI with C++, how does dZh0 configure the UI? I’m curious how to do it!
So when I checked it in this code, UpdateHp was 0. For your information, the SetHp function returns. returnHp / MaxHp; returns this value. But I don’t understand why it comes out as 0…
However, when I initialized HpBarProgress in NativeConstruct(), it doesn’t seem to be null.
void UOLHpBarWidget::NativeConstruct()
{
Super::NativeConstruct();
// 해당 컨트롤을 이름으로 찾기
HpBarProgress = Cast<UProgressBar>(GetWidgetFromName(TEXT("HpBar")));
ensure(HpBarProgress);
// CharacterBase의 함수 가져오기
APawn* Player = GetOwningPlayerPawn(); // Player 가져오기
ensure(Player);
IOLHpInterface* PlayerInterface = Cast<IOLHpInterface>(Player);
ensure(PlayerInterface);
PlayerInterface->SettingHpBar(this);
if (HpBarProgress)
{
HpBarProgress->SetPercent(1.f);
UE_LOG(LogTemp, Display, TEXT("SetPercent"));
}
UpdateHpBar();
}
When I created the code as above, a log called SetPercent appeared on the screen. Does that mean it exists when the log is displayed like this?
Is it a more stable way to make it in blue print than in C++??