UE 4.27 기준 UI중에 블루프린트로 UTextBlock의 Text 설정을 함수를 만들어서 바인딩할 수 있으나 C++에서 해당 기능을 구현 중에 있었는데, 관련 델리게이트가 보이길래 UTextBlock의 TextDelegate를 이용하여 특정 이벤트가 발생했을 때 TextDelegate함수를 호출하고 다음과 같이 UI에 해당 내용을 바꾸려고 했다.
// UPROPERTY(VisibleAnywhere, Category = UI, Meta = (PrivateAccess = true));
// class UTextBlock* AmmoText;
AmmoText->SetText(AmmoText->TextDelegate.Execute());
하지만 실제로는 한번만 실행되고 해당 델리게이트가 Empty가 되어 어디서 Unbind()가 되나 했더니
void UTextBlock::SetText(FText InText)
{
Text = InText;
TextDelegate.Unbind(); // ????
if ( MyTextBlock.IsValid() )
{
TAttribute<FText> TextBinding = GetDisplayText();
MyTextBlock->SetText(TextBinding);
}
}
해당 객체의 SetText를 호출하면 실제 텍스트를 바꾸는 것뿐만아니라 바인딩된 델리게이트도 해제하고 있었다.
따라서 다음과 같이 UI 클래스에서 직접 싱글캐스트 델리게이트를 선언해서 그 객체에 바인딩하는 것으로 일단 Unbind()를 회피했다.
UProgressBar
UProgressBar의 SetPercent는 바인드된 함수를 제거하지는 않아서 당연히 UTextBlock도 바인드된 함수를 안 건드리는 줄 알았다.
void UProgressBar::SetPercent(float InPercent)
{
Percent = InPercent;
if (MyProgressBar.IsValid())
{
MyProgressBar->SetPercent(InPercent);
}
}
// 실제 사용코드
if (HealthBar->PercentDelegate.IsBound())
{
HealthBar->SetPercent(HealthBar->PercentDelegate.Execute());
}
else
{
LOG(Warning, TEXT("HealthBar PercentageDelegate Is Not Bound"));
}
- 클래스 정의
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "../GameCore.h"
#include "Blueprint/UserWidget.h"
#include "FPSHUDWidget.generated.h"
DECLARE_DELEGATE_RetVal(FText, FOnAmmoChangedDelegate);
DECLARE_DELEGATE_RetVal(FText, FOnMaxAmmoChangedDelegate);
/**
*
*/
UCLASS()
class GAMECORE_API UFPSHUDWidget : public UUserWidget
{
GENERATED_BODY()
friend class AMainPlayer;
friend class AMainPlayerController;
public:
virtual void NativeConstruct() override;
virtual void BeginDestroy() override;
private:
void BeginPlay(class AMainPlayer* MainPlayer);
void UpdatePlayerStat();
void UpdateWeaponStat();
private:
UPROPERTY(VisibleAnywhere, Category = UI, Meta = (PrivateAccess = true));
class UProgressBar* ArmorBar;
UPROPERTY(VisibleAnywhere, Category = UI, Meta = (PrivateAccess = true));
class UProgressBar* HealthBar;
UPROPERTY(VisibleAnywhere, Category = UI, Meta = (PrivateAccess = true));
class UTextBlock* AmmoText;
UPROPERTY(VisibleAnywhere, Category = UI, Meta = (PrivateAccess = true));
class UTextBlock* MaxAmmoText;
FOnAmmoChangedDelegate FOnAmmoChanged;
FOnMaxAmmoChangedDelegate FOnMaxAmmoChangedDelegate;
};
- 함수 바인딩
// Weapon.h
//
// UFUNCTION()
// FText GetAmmoInText() const { return FText::FromString(FString::FromInt(Ammo)); }
// UFUNCTION()
// FText GetMaxAmmoInText() const { return FText::FromString(FString::FromInt(MaxAmmo)); }
// FPSHUD.cpp
// 바인딩
FOnAmmoChanged.BindUFunction(Weapon, TEXT("GetAmmoInText"));
FOnMaxAmmoChangedDelegate.BindUFunction(Weapon, TEXT("GetMaxAmmoInText"));
// 호출
if (FOnAmmoChanged.IsBound())
{
AmmoText->SetText(FOnAmmoChanged.Execute());
}
else
{
LOG(Warning, TEXT("AmmoText TextDelegate Is Not Bound"));
}
'C++ > Unreal Engine' 카테고리의 다른 글
[UE4] Behavior Tree 정리 (0) | 2021.10.15 |
---|---|
[UE4] 디버깅 기록 PostActorCreated / 월드에서 스폰시 (0) | 2021.10.11 |
[UE4] 디버깅 기록 Delegate / BeginDestroy (0) | 2021.10.09 |
[UE4] 생성과 관련된 호출 함수 (0) | 2021.10.08 |
[UE4] 게임 플레이 프레임워크 (GameMode, PlayerController, Pawn) (0) | 2021.09.30 |