팀 프로젝트와 개인 프로젝트를 병해앟다 보니 이번 개발일지는 조금 늦어졌습니다.
이번에 개발하여 추가한 기능은 Stamina UI와 InterAction UI입니다.
아직 캐릭터의 실제 행동에 따라 스테미나가 소모되거나 회복되는 로직까지는 연결되지 않았지만,
추후 캐릭터 행동 로직과 연동할 수 있도록 UI 구조와 기능 구현은 완료해 두었습니다.

작업 순서
1. Stamina User widget 생성
2. 해당 Widget Blueprint의 부모로 설정해줄 UserWidget C++ 클래스 생성
3. StatComponent에 Stamina 변동사항 델리게이트 이벤트 생성
4. Character의 SetupPlayerUiWidget에 Stamina Ui 관련 Delegate 이벤트 bind
5. Main Ui Widget Blueprint에 적용
UI Framework Flow Chart

현재는 다음과 같이 Ui FrameWork Flow Chart를 구현해보았습니다.
Stamina User Widget 만들기

Main Ui Widget Blueprint에 모든 기능을 직접 구현하지 않고, 기능별 모듈화를 위해 Stamina Widget Blueprint를 별도로 분리하여 구현했습니다.
이를 통해 Main Ui에서는 스테미나 UI를 하나의 독립된 Widget처럼 관리할 수 있으며, 추후 위치 이동, 크기 조절, 배치 수정이 용이하도록 구성했습니다.
Widget Blueprint의 부모로 설정해줄 UserWidget C++ 클래스 생성
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "PlayerStaminaProgressBarWidget.generated.h"
/**
*
*/
UCLASS()
class NEVERNESS_API UPlayerStaminaProgressBarWidget : public UUserWidget
{
GENERATED_BODY()
public:
UPlayerStaminaProgressBarWidget(const FObjectInitializer& ObjectInitializer);
protected:
virtual void NativeConstruct() override;
public:
FORCEINLINE void Set_Up_Stamina(float _fCurrentStamina, float _fMaxStamina)
{
CurrentStamina = _fCurrentStamina;
MaxStamina = _fMaxStamina;
};
void UpdateProgressBar(float _fCurrentStamina, float _fMaxStamina);
bool Get_HasPlayedStaminaAnimation() { return HasPlayedStaminaRenderOpacity; }
void Set_HasPlayedStaminaAnimation(bool _bPlayed) { HasPlayedStaminaRenderOpacity = _bPlayed; }
void PlayUiAnimation();
void ResetRenderOpacity();
private:
TObjectPtr<class UProgressBar> StaminaProgressBar;
TObjectPtr<class UTextBlock> CurrentStaminaText;
UPROPERTY()
float CurrentStamina;
UPROPERTY()
float MaxStamina;
#pragma region Stamina UI Animation 관련
/* BindWidgetAnim (Blueprint 애니메이션과 자동 연결 )*/
/* Transient 직렬화 제외, 런타임에만 유효한 포인터임을 명시*/
UPROPERTY(Transient, meta = (BindWidgetAnim))
TObjectPtr<class UWidgetAnimation> Render_Opacity_StaminaProgressBar;
UPROPERTY(Transient, meta = (BindWidgetAnim))
TObjectPtr<class UWidgetAnimation> Render_Opactiy_StaminaText;
UPROPERTY()
bool HasPlayedStaminaRenderOpacity = false;
#pragma endregion
};
현재 UserWidget에서는 ProgressBar, TextBlock을 사용하므로 2개의 객체를 변수 선언을 해주었으며,
Ui Animation 또한 사용할 것이므로 Animation 변수 또한 추가해주었다.
여기서 주의해야할 점이 Animation 변수명 같은 경우 Ui 애니메이션 변수명과 같아야 한다는 점이다.

또한 Blueprint에서 생성한 Animation을 C++ 클래스의 변수와 연동하기 위해 UPROPERTY() 설정을 사용 했습니다.
특히 BindWidgetAnim 메타 테그를 통해 Widget Blueprint에 생성된 Widget Animation을 C++ 변수와 자동으로 바인딩할 수 있도록 구성했습니다.
| Transient | 이 변수가 저장 대상이 아니라 런타임에서만 유효한 임시 참조의 의미 |
| BindWidgetAnim | UMG Blueprint에 있는 애니메이션과 C++ 변수를 이름 기준으로 자동 바인딩 해주는 메타 태그 |

StatComponent에 Stamina 변동사항 델리게이트 이벤트 생성
DECLARE_MULTICAST_DELEGATE_TwoParams(FOnStaminaChangedDelegate /* Delegate 이름*/, float /* fCurrentStamina ( 현재 Stamina) */, float /*fMaxStamina ( Max Stamina)*/)
Character의 SetupPlayerUiWidget에 Stamina Ui 관련 Delegate 이벤트 bind

Main Ui Widget Blueprint에 적용

다음과 같이 각 UI 기능을 별도의 Widget Blueprint로 분리하여 모듈화한 모습을 볼 수 있습니다.
InterAction Ui 또한 위와 동일한 방식으로 구현하였습니다.
Why? 분리해서 구현했는지.
이렇게 UI를 기능별로 분리한 이유는 Main UI Widget에 모든 기능을 직접 구현할 경우 구조가 복잡해지고, 유지보수와 수정이 어려워 질 수 있다고 생각했습니다.
따라서 Stamina UI, InterAction UI처럼 역할이 명확한 UI를 별도의 Widget으로 구성하여, Main UI에서는 배치와 관리만 담당하도록 설계하였습니다.
이를 통해 추후 UI의 위치 변경, 크기 조절, 기능 수정이 필요할 때 해당 Widget만 수정되므로 확장성과 유지보수성이 향상됩니다.
'Unreal Project > 이환 모작 포토폴리오 개발일지' 카테고리의 다른 글
| [개발일지] 이환 모작_04 Inventory 기능과 Item UI 구현 (0) | 2026.05.20 |
|---|---|
| [개발일지] 이환 모작_02 ( Hp Bar Widget ) (0) | 2026.05.08 |
| [개발일지] 이환 모작_01 ( Character, GameMode, PlayerController) (2) | 2026.04.30 |
