안선생의 개발 블로그

[UE5 멀티플레이 게임 만들기] 12. 화면에 스킬이미지 띄우기 본문

언리얼/멀티플레이 게임 만들어보자

[UE5 멀티플레이 게임 만들기] 12. 화면에 스킬이미지 띄우기

안선생 2024. 1. 25. 14:23

저번에는 데이터 에셋을 만들었고 이 데이터 에셋 기반으로 스킬 정보를 화면에 띄우려고 해요.

 

그러면 위젯에 이미지를 바꿔야겠죠.

 

위젯은 모두 WidgetController에 의존하니 \

 

 

WidgetController 를 작성해 줄게요

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "JHWidgetController.generated.h"


class USkillInfo;
class USkillComponent;

USTRUCT(BlueprintType)
struct FWidgetControllerParms
{
	GENERATED_BODY()

	FWidgetControllerParms() {}
	FWidgetControllerParms(USkillComponent* SC) :
		SkillComponent(SC){}

	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	TObjectPtr<USkillComponent> SkillComponent;

};
/**
 * 
 */
UCLASS(BlueprintType, Blueprintable)
class JH_MULTI_RPG_API UJHWidgetController : public UObject
{
	GENERATED_BODY()
public:

	void SetWidgetControllerParms(const FWidgetControllerParms& Parms);
	virtual void BindCallbacksToFunctions();
public:

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "SkillInfo")
	TObjectPtr<USkillInfo> SkillInfo;

	UPROPERTY(BlueprintReadOnly, Category = "SkillComponent")
	TObjectPtr<USkillComponent> SkillComponent;

};

 

WidgetController는 필요한 정보를 갖고 있어야 돼요.

일단은 SkillComponent가 필요하니  SkillComponent를 가져올게요.

 

앞으로 가져올게 많을 수 있으니 구조체로 관리할게요

 

// Fill out your copyright notice in the Description page of Project Settings.


#include "UI/WidgetController/JHWidgetController.h"
#include "Inventory/JHInventoryComponent.h"
#include "Character/Component/HealthComponent.h"

void UJHWidgetController::SetWidgetControllerParms(const FWidgetControllerParms& Parms)
{
	SkillComponent = Parms.SkillComponent;
}

void UJHWidgetController::BindCallbacksToFunctions()
{
	/** 각 컨트롤러에서 구현하세요*/
}

함수를 호출하면 SkillComponet를 가져와요. 

 

SkillComponent는 Character에 있죠

 

즉 Character에서 가져와야 돼요.

 

WidgetController는 HUD에서 관리하고 캐릭터에서 호출해요 

 

일단 HUD로 가볼게요.

 

InitOverlay함수로 가서 수정해 줄게요

void AJHHUD::InitOverlay(USkillComponent* SC)
{
	OverlayWidget = CreateWidget<UJHUserWidget>(GetWorld(), OverlayWidgetClass);
	
	OverlayWidgetController = NewObject<UJHWidgetController>(this, OverlayWidgetControllerClass);
	const FWidgetControllerParms WidgetController(SC);
	OverlayWidgetController->SetWidgetControllerParms(WidgetController);
	

	OverlayWidget->SetWidgetController(OverlayWidgetController);
	OverlayWidgetController->BindCallbacksToFunctions();
	OverlayWidget->AddToViewport();

}

자 여기서 캐릭터에서 가져온 SkillComponent로 구조체를 만들고 OverlayWidgetController에 설정해 줬어요.

 

그리고 BindCallbacksToFunctions를 호출해 줬어요 이 함수는 이름 그대로 함수를 바인딩해주는 함수예요.

 

일단 이렇게 하고 컴파일해볼게요.

 

 

 

 

그런 다음 WidgetController를 부모로 하는 OverlayWidgetController를 만들어줄게요.

 

이 위젯컨트롤러는 OverlayWidget들을 관리해 주는 컨트롤러예요.

 

인벤토리는 Inventory컨트롤러를 따로 만들어서 관리해 주는 게 좋겠죠 아무래도

 

하나로 하면 관리하기 힘들 거예요 그래서 각 위젯에 맞는 컨트롤러를 만들어줄게요.

 

생성해 주시고

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "UI/WidgetController/JHWidgetController.h"
#include "OverlayWidgetController.generated.h"

struct FJHSkillInfo;


DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FSkillInfoSignature, const FJHSkillInfo&, SkillInfo);



/**
 * 
 */
UCLASS(BlueprintType,Blueprintable)
class JH_MULTI_RPG_API UOverlayWidgetController : public UJHWidgetController
{
	GENERATED_BODY()
public:
	virtual void BindCallbacksToFunctions() override;

	UPROPERTY(BlueprintAssignable,Category="SKillInfo")
	FSkillInfoSignature SkillInfoSignature;
	
};

델리게이트를 하나 만들어줄게요. 스킬정보를 갖고 있는 델리게이트예요

 

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam 

다이내믹은 C++ , Bluepirnt에서 가능하고 

멀티케스트는 여러 개 바인딩할 수 있다는 뜻이에요.

OneParam은 말 그대로 하나의 파라미터를 갖고 있어요.

 

부모에게 상속받은 함수를 override 해주고

 

델리게이트를 블루프린트에서 바인딩할 거 기 때문에 하나 만들어줬어요.

 

cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "UI/WidgetController/OverlayWidgetController.h"
#include "Skill/SkillComponent.h"
#include "Skill/SkillInfo.h"


void UOverlayWidgetController::BindCallbacksToFunctions()
{
	for (auto& SkillName : SkillComponent->GetActivatableSkillNames())
	{
		FJHSkillInfo Info = SkillInfo->FindSkillInfo(SkillName);
		SkillInfoSignature.Broadcast(Info);
	}
}

바인딩 함수는 간단해요 그냥 for문으로 활성화된 스킬을 찾아서 Broadcast(방송)해주시면 돼요.

그러면 바인딩된 모든 델리게이트에 값을 전달해 줄 거예요.

 

그럼 바인딩하로 가야겠죠

 

Widget은 C++에서 함수나 델리게이트를 만들고 블루프린트에서 로직을 짤라고 해요.

 

 

컴파일해 줄게요

 

OverlayWidget에 가서

 

WidgetController를 가져와서 캐스팅해줄게요 그런 다음에 SkillOverlay에도 SetWidgetController 해서 WidgetController를 설정해 줄게요 이 함수는 호출하면 바로 WidgetControllerSet이 실행됩니다. 코드참조

 

그럼 SkillOverlay에 가서 이벤트를 호출해 줄게요.

 

SKillOverlay에요

 

여기도 간단해요 이벤트로 호출해 주고 Cast후 OverlayWidgetController로 가져와요

 

그런 저희가 만든 델리게이트가 있겠죠 

 

델리게이트를 바인딩해줘서 호출되면 저 로직을 실행해요 

 

저 바인딩될 때 호출되는 거는 일단 저희가 SkillInfo를 전달해 줬죠 

 

거기서 받은 SkillInfo에 SKillInput을 찾아서 Q슬롯에 맞는 이미지 W슬롯에 맞는 이미지를 설정해 줍니다.

 

그렇게 8개 설정해 주시고 실행해볼게요.

 

그러면 이렇게 스킬슬롯에 이미지가 채워진 거를 볼 수 있어요.

 

DataAsset에서 설정해 줬으니 DataAsset에서 SkillInput을 바꿔주시면 거기에 맞는 이미지로 바뀔 거예요!

 

 

 

DataAsset을 이용하여 스킬을 관리해 봤어요 다음에는 인벤토리를 해볼게요!