BossFight - Player UI(HP)

๊น€๋Œ€๊ฒธยท2025๋…„ 5์›” 7์ผ

Player UI(HP)

์ด๋ฒˆ์—๋Š” ํ”Œ๋ ˆ์ด์–ดUI์„ ์ž‘์„ฑํ•˜๊ณ , ํ™”๋ฉด์— ์ถœ๋ ฅ ์‹œ์ผœ๋ณด์ž, ์ถ”๊ฐ€๋กœ HP๋ฅผ ์—ฐ๋™์‹œ์ผœ, HP๊ฐ€ ๊ฐ์†Œ๋ ๋•Œ๋งˆ๋‹ค UI๊ฐ€ ๊ฐฑ์‹ ๋˜๋Š” ๊ธฐ๋Šฅ๋„ ๊ตฌํ˜„ ํ•ด๋ณด์ž.

BFWidgetBase๋ฅผ ์ƒ์†๋ฐ›์•„ TWBP_Bar๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์œ„์™€๊ฐ™์ด PreConstruct๋ฅผ ๊ตฌํ˜„ ํ•ด์ฃผ์—ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด, Bar์˜ ํฌ๊ธฐ์™€, ์ฑ„์›Œ์ง€๋Š” ์ƒ‰์ƒ์„ ์ •์˜ ํ• ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

๊ทธํ›„ BFWidgetBase๋ฅผ ์ƒ์† ๋ฐ›์•„ ์‹ค์ œ PlayerUI๊ฐ€ ๋  WBP_Player_UI๋ฅผ ์ž‘์„ฑ ํ•˜๊ณ  ์•„๋ž˜ ์‚ฌ์ง„๊ณผ ๊ฐ™์ด ๋ฐฐ์น˜ ํ•ด์ฃผ์—ˆ๋‹ค.

์ƒ‰์ƒ์„ ์ดˆ๋ก์ƒ‰์œผ๋กœ ํฌ๊ธฐ๋ฅผ 500 x 20์œผ๋กœ ์„ค์ • ํ•˜์˜€๋‹ค.

๋‹ค์Œ์œผ๋กœ ํ”Œ๋ ˆ์ด์–ด ์บ๋ฆญํ„ฐ์˜ HP๋ฅผ ์—ฐ๋™ ํ•ด์•ผํ•œ๋‹ค. ์ด๋Š” PlayerUIComponent์—์„œ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ๋ฅผ ์„ ์–ธ ํ•˜์—ฌ ๊ตฌํ˜„ ํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ๋‹ค.

๐ŸŽฎ UPlayerUIComponent.h

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPercentChangedDelegate, float, NwePercent);

class IInteractablePropInterface;

UCLASS()
class BOSSFIGHT_API UPlayerUIComponent : public UPawnUIComponent
{
	GENERATED_BODY()
	// ์ค‘๋žต
	UPROPERTY(BlueprintAssignable)
	FOnPercentChangedDelegate OnCurrentHealthChanged;
};

์œ„์™€ ๊ฐ™์ด ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ๋ฅผ ์„ ์–ธํ•˜๊ณ , UPROPERTY(BlueprintAssignable)์„ ํ†ตํ•ด ๋ธ”๋ฃจํ”„๋ฆฐํŠธ์—์„œ ํ• ๋‹น ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€๋‹ค.

๋‹ค์Œ์œผ๋กœ AttributeSet์• ์„œ HP๊ฐ€ ๊ฐ์†Œ ๋ ๋•Œ๋งˆ๋‹ค ํ˜„์žฌ HP์™€ ์ตœ๋Œ€ HP์˜ ๋น„์œจ์„ ๊ตฌํ•˜๊ณ  Brodcast๋ฅผ ํ†ตํ•ด ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ๋ฅผ ์‹คํ–‰ ์‹œํ‚ค๋„๋ก ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑ ํ•˜์ž.

void UBFAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
	if (!CachedPawnUIInterface.IsValid())
	{
		CachedPawnUIInterface = TWeakInterfacePtr<IPawnUIInterface>(Data.Target.GetAvatarActor());
	}

	if (Data.EvaluatedData.Attribute == GetCurrentHPAttribute())
	{
		const float NewCurrentHP = FMath::Clamp(GetCurrentHP(), 0.0f, GetMaxHP());
		SetCurrentHP(NewCurrentHP);

		if (UPlayerUIComponent* PlayerUIComponent = CachedPawnUIInterface->GetPlayerUIComponent())
		{
			PlayerUIComponent->OnCurrentHealthChanged.Broadcast(GetCurrentHP() / GetMaxHP());
		}
	}
    // ์ค‘๋žต
}

์œ„์™€๊ฐ™์ด Player์˜ HP๊ฐ€ ๋ณ€๋™ ํ•  ๋•Œ OnCurrentHealthChanged๋ธ๋ฆฌ๊ฒŒ์ดํŠธ๋ฅผ Broadcast() ํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑ ํ•˜์˜€๋‹ค.

์ดํ›„ WBP_PlayerUI์—์„œ ํ•ด๋‹น ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ์— ์•„๋ž˜์™€๊ฐ™์ด ๋…ธ๋“œ๋ฅผ ์—ฐ๊ฒฐ ํ•˜์˜€๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ GameplayAbility๋ฅผ ํ†ตํ•ด Widget์„ ์ƒ์„ฑ ๋ฐ ๋ถ€์ฐฉ ํ•ด๋ณด์ž.

GameplayAbility๋ฅผ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š” BeginPlay์—์„œ UI๋ฅผ ๋ถ€์ฐฉํ•ด๋„ AttributeSet์ด ์•„์ง ์ดˆ๊ธฐํ™” ๋˜์ง€ ์•Š์•„์„œ, UI๊ฐ€ ๊ฐฑ์‹ ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, Ability๋ฅผ OnGiven์œผ๋กœ ์„ค์ •ํ•˜์—ฌ, AbilitySystem ๋ฐ AttributeSet์ด ์ดˆ๊ธฐํ™” ๋˜๊ณ ๋‚˜์„œ ์ž‘๋™ ํ•˜๋„๋ก ํ•˜์˜€๋‹ค.

์œ„์™€ ๊ฐ™์ด Base Ability๋ฅผ ์ž‘์„ฑํ•˜๊ณ , ์ž์‹ Ability๋ฅผ ์ƒ์„ฑ WidgetClass๋ฅผ ํ• ๋‹นํ•˜์—ฌ, DA_Player์— ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ๋‹ค.

์‹คํ–‰ ๊ฒฐ๊ณผ

๊ฒŒ์ž„์„ ์‹คํ–‰ํ•˜๋ฉด HP Bar๊ฐ€ ๊ฐ€๋“ ์ฐฌ ์ƒํƒœ๋กœ ์‹œ์ž‘ ํ•œ๋‹ค.

์ž„์‹œ๋กœ Hํ‚ค์— HP๋ฅผ ๊ฐ์†Œ ์‹œํ‚ค๋Š” GameplayEffect๋ฅผ ์ž‘๋™ ์‹œํ‚ค๋„๋ก ํ•˜๊ณ  ์‹คํ–‰ ์‹œ์ผœ๋ณธ ๊ฒฐ๊ณผ, ๊ฐ์†Œ๋œ ๋งŒํผ HP_Bar๊ฐ€ ์ค„์–ด๋“œ๋Š” ๊ฒƒ์„ ํ™•์ธ ํ•˜์˜€๋‹ค.

๋‹ค์Œ์—๋Š” ์Šคํ…Œ๋ฏธ๋‚˜ UI๋ฅผ ๊ตฌํ˜„ ํ•˜๊ณ , ๋‹ฌ๋ฆฌ๊ธฐ ์ž‘๋™์‹œ ์Šคํƒœ๋ฏธ๋‚˜๊ฐ€ ์ง€์†์ ์œผ๋กœ ๊ฐ์†Œ ํ•˜๋Š” ๊ฒƒ์„ ๊ตฌํ˜„ ํ•ด๋ณด๊ฒ ๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€