본문 바로가기

게임프로그래밍/실습2

[실습2] 19. 초기값 위젯에 브로드캐스팅하기기

1. 서론

 

오버레이 위젯은 지금 자신의 위젯 컨트롤러를 가지고 있으며 그렇기에 위젯 컨트롤러에 접근할 수 있다. 물론 위젯 컨트롤러는 자신을 소유하고 있는 대상이 누군지 알지 못한다. 단방향 의존성으로 구성되어 있기 때문이다.

 

위젯 컨트롤러가 알고 있는 것은 그저 자신이 가지고 있는 4개의 주요 변수들이다. 컨트롤러는 자신을 소유하고 있는 위젯에 대해 알지 못하기 때문에 이러한 변수들을 브로드캐스트하여 자신을 소유하고 있는 위젯에게 그 값을 넘긴다.

 

이제 브로드캐스트하는 방법을 알아보자.


2. 위젯 컨트롤러에서 브로드캐스트 하기

 

위젯 컨트롤러 클래스로 들어가자. 이때 오버레이 위젯 컨트롤러가 아닌 베이스 위젯 컨트롤러로 들어갈 것이다.

 

퍼블릭 공간에 함수를 선언한다.

virtual void BroadCastInitialValues();

 

 

함수의 정의는 자식 클래스에서 진행할 것이다. cpp파일에 함수 본문만 만들어놓고 비워둔 채로 놓아둔다.

 

이제 오버레이 위젯 컨트롤러로 들어가 오버라이드하자.

 

class PRACTICE2_API UOverlayWidgetController : public UAuraWidgetController
{
    GENERATED_BODY()

public:
    virtual void BroadCastInitialValues() override;
    
};

 

그리고 이제 브로드캐스트를 하기 위해 델리게이트를 만들 것이다.

 

헤더파일에 델리게이트를 선언해주자.

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnAttributeChanged, float, NewHealth);

 

이제 클래스 내부에서 델리게이트를 지정할 변수를 만들자.

class PRACTICE2_API UOverlayWidgetController : public UAuraWidgetController
{
	GENERATED_BODY()

public:
	virtual void BroadCastInitialValues() override;

	UPROPERTY(BlueprintAssignable, Category = "GAS|Attributes")
	FOnAttributeChanged OnHealthChanged;

	UPROPERTY(BlueprintAssignable, Category = "GAS|Attributes")
	FOnAttributeChanged OnMaxHealthChanged;
	
};
FOnAttributeChanged OnHealthChanged;

 

이 구문은 해당 델리게이트 타입으로 인스턴스 객체를 생성한 것이다. 이제 이 인스턴스에 함수를 바인딩하여 델리게이트를 조작할 수 있게 된다.

 

이제 델리게이트가 있으니 브로드캐스트 할 수 있어야 한다.cpp파일로 들어가자.

 

void UOverlayWidgetController::BroadCastInitialValues()
{
    OnHealthChanged.Broadcast();
}

 

이렇게 브로드캐스트 할 수 있다. 체력값을 가져와야하는데 이것을 어떻게 가져올 수 있을까?

어트리뷰트 세트에서 이 값을 가져와야할 수 있을 것이다.


2. 어트리뷰트세트에서 밸류 가져오기

 

어트리뷰트 세트를 저장하는 변수는 부모 클래스에 이미 존재한다. 그러면 이것을 우리가 원하는 어트리뷰트 세트로 캐스팅하여 사용할 수 있을 것이다.

 

void UOverlayWidgetController::BroadCastInitialValues()
{
    const UAuraAttributeSet* AuraAttributeSet = CastChecked<UAuraAttributeSet>(AttributeSet);
    
    OnHealthChanged.Broadcast(AuraAttributeSet->GetHealth());
    OnMaxHealthChanged.Broadcast(AuraAttributeSet->GetMaxHealth());
}

 

이제 이 함수를 호출할 시기를 알아야 한다. AttributeSet가 생성된 것은 물론 위젯 컨트롤러 또한 정상적으로 생성이 다 되어 있어야 한다.

 

HUD에서 이닛 오버레이 함수가 있고 이 곳에서 오버레이 위젯을 설정한다. 설정이 끝났다는 것은 위에 말한 필요 항목들이 다 있다는 것이고 그럼 정상적으로 함수를 실행시킬 수 있다.

 

HUD cpp 파일로 돌아가 이를 실행시키자.

 

void AAuraHUD::InitOverlay(APlayerController* PC, APlayerState* PS, UAbilitySystemComponent* ASC, UAttributeSet* AS)
{
    checkf(OverlayWidgetClass, TEXT("Overlay Widget Class uninitialized, fill out BP_AuraHUD"));
    checkf(OverlayWidgetControllerClass, TEXT("Overlay Widget Controller Class uninitialized, fill out BP_AuraHUD"));
    
    UUserWidget* Widget = CreateWidget<UUserWidget>(GetWorld(), OverlayWidgetClass);
    OverlayWidget = Cast<UAuraUserWidget>(Widget);

    const FWidgetControllerParams WidgetControllerParams(PC, PS, ASC, AS);
    UOverlayWidgetController* WidgetController = GetOverlayWidgetController(WidgetControllerParams);

    OverlayWidget->SetWidgetController(OverlayWidgetController);
    // 이 아래 추가
    WidgetController->BroadCastInitialValues();
    

    Widget->AddToViewport();
    
}

 

이렇게 하면 올바른 시점에 브로드캐스트를 할 수 있다.

 

컴파일하고 에디터로 들어가 블루프린트 단위에서도 제대로 시행되는지 확인하자.


3. 블루프린트에서 확인하기

 

오버레이 위젯 블루프린트로 들어가자. 오버레이 위젯뿐 아니라 체력과 마나 위젯도 동일한 위젯 컨트롤러로 지정할 것이다.

 

 

위젯 컨트롤로 세트라는 함수를 가져오자. 해당 함수는 C++에서 위젯 컨트롤러가 정상적으로 설정되면 그 다음 자동으로 호출되는 함수이다.

 

 

셋 위젯 컨트롤러가 블루프린트 호출가능 함수기 때문에 이런 식으로 설정하는 것이 가능하다.

 

Set widget controller 함수는 다시 widget controller set 함수를 호출한다. 즉 체력과 마나 위젯으로 들어가 다시  widget controller set 를 시행 시킬 수 있다는 것이다.

 

체력 위젯 으로 들어가자.

 

 

위젯 컨트롤러 변수는 단순한 UObject이기 때문에 이를 캐스팅해주어야 한다. 하지만 오버레이 위젯 클래스가 보이지 않는다.

 

C++ 파일로 들어가 다시 설정해주자.

 

UCLASS(BlueprintType, Blueprintable)
class PRACTICE2_API UOverlayWidgetController : public UAuraWidgetController
{

 

Blueprintable 는 해당 클래스를 기반으로 블루프린트 클래스를 만들 수 있다는 것이다.

BlueprintType 은 해당 클래스를 블루프린트에서 변수로 사용할 수 있게 설정하는 것이다.

 

 

이제 델리게이트에 접근할 수 있는 것을 볼 수 있다.

 

이제 저 델리게이트가 브로드 캐스트 되면 어떤 작업을 할지 지정하면 된다.

 

여기서 Assign하고 Bind가 있는데 Assign은 델리게이트에 함수들을 추가하는 것이고 Bind는 단 하나의 함수만 델리게이트와 연결 하는 것이라고 한다. 솔직히 무슨 차인지 잘 모르겠지만 대충 보면 Assign은 여러 함수를 추가할 수 있고 Bind는 하나의 기능만 추가할 수 있다고 보면 될 것같다.

 

연결하기 전에 할게 있다. 이제 오버레이 위젯 클래스는 블루프린트로 만들 수 있다. 그냥 C++클래스에 캐스팅하는 것이 아닌 블루프린트로 만들어서 사용하자.

 

이렇게 만들고 나면 BP_HUD에서도 설정을 바꿔주어야 한다.

 

 

이제 바인딩을 할 수 있게 되었다. 밑의 빨간 노드는 브로드캐스트가 발생하면 할 작업을 연결하는 노드이다.

 

이제 체력과 최대체력을 가져올 수 있으니 프로그레스바를 채우는 것도 가능해진다.

 

 

이렇게 체력과 최대 체력을 변수로 만들어놓자.

 

이제 백분률을 설정하면 되는데 현재 이 클래스는 자식 클래스이다. 글로벌 프로그레스바 클래스로 가 함수를 만들어 자식클래스에서 사용하도록 하자.

 

이제 이 이후는 계속해서 블루프린트 작업에 관한 부분이라 여기까지 포스팅 하도록 하겠다.