본문 바로가기
언리얼엔진 개발/Developing

[UnrealEngine5] 공격 받으면 줄어드는 HP 위젯 구현하기

by yeni_0224 2023. 7. 21.
728x90
반응형

01 아이템박스 클래스와 블루프린트 생성 및 배치

box class를 만들어주고, 블루프린트도 하나 만들어주고 레벨에 배치해준다.

플레이어가 총알을 발사해 저 아이템 박스에 닿으면 hp가 깎이는걸 눈으로 보이게까지 구현할 것이다.

02 위젯 블루프린트 생성

아이템 박스 위에 띄울 위젯을 만들어준 후 아이템박스 BP 클래스에 이 위젯을 할당시켜줄 것이다.

위젯 컴포넌트 변수를 만들어주고, 

	//위젯 클래스의 변수
    UPROPERTY()
	class UItemBoxWidget* boxWidget;
    
    //위젯 컴포넌트
    UPROPERTY(EditDefaultsOnly)
	class UWidgetComponent* widgetComp;

그 컴포넌트 안에 위젯 블루프린트를 넣어주었다.

widgetComp = CreateDefaultSubobject<UWidgetComponent>(TEXT("widgetComp"));
	widgetComp->SetupAttachment(RootComponent);
	widgetComp->SetWidgetSpace(EWidgetSpace::Screen);
	ConstructorHelpers::FClassFinder<UUserWidget> hpWidget(TEXT("/Script/UMGEditor.WidgetBlueprint'/Game/ThirdPerson/Blueprints/WBP_ItemBox.WBP_ItemBox_C'"));
	if(hpWidget.Succeeded())
	{
		widgetComp->SetWidgetClass(hpWidget.Class);
	}

EWidgetSpace::Screen으로 설정하면 아이템박스의 어느 방향에서 보아도 위젯이 보이고,

EWidgetSpace::World로 설정하면 지정된 방향에서만 위젯이 보인다.

위젯 블루프린트를 만들 때는 c++ 클래스 우클릭한 후 위젯 블루프린트를 만들지 말고

블루프린트 클래스를 만든 후 위젯C++ 클래스로 Reparent 해주는 것을 추천한다.

위젯 편집할 수 있는 캔버스 화면이 안뜬다.

03 HP가 깎이는 부분 구현하기

//hp
	int32 hp;
	int32 maxHP = 10;	 
	UFUNCTION(BlueprintCallable)
	FORCEINLINE void TakeHP(int32 pwer) { maxHP -= pwer; }

아이템 박스의 hp 변수와 최대 hp 변수 값을 만들어준다.

일정 데미지가 발생하게되면 max hp에서 값이 깎이도록 inline 함수를 만들어주었다. 이렇게 간단하게 구현할 수 있는 것들은 인라인 함수로 구현할 수도 있지만, 현업에서는 인라인 함수가 간혹 찾기 힘들기 때문에 경우에 따라 불편함이 발생하다고도 한다. 하지만 이 블로그에서 등장한 적이 없으니까 이렇게 새로운걸 써보면서 스킬 늘려가기~

04 충돌할 때 HP가 깎이는 조건 추가하기

총알이 아이템박스에 닿았을 때 hp가 깎여야하기 때문에 Overlap 함수를 써주어야한다.

먼저 충돌 함수를 beginplay에서 바인딩 해주고, 게임 플레이할 때 최초 hp는 maxhp값과 같다고 지정해준다.

이렇게 하면 나중에 위젯이 활성화 되었을 때 처음 보여지는 모습은 hp가 꽉 찬 모습이다.

boxComp->OnComponentBeginOverlap.AddDynamic(this, &AItemBox::OnOverlap);
hp = maxHP;

헤더파일에 UFUNCTION써주고 아래에 함수를 써준다. 매개변수 찾기 위해서 일부러 바인딩 먼저 해주었다.

UFUNCTION()
	void OnOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

그 다음 실제 HP가 깎이는 부분을 구현할것이다.

void AItemBox::OnOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp,
	int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	bullet = Cast<ABullet>(OtherActor);
	UE_LOG(LogTemp, Warning, TEXT("OnOverlap : %s"), *OtherActor->GetName())
	if(bullet)
	{		
		TakeHP(bullet->attkScore);
		UE_LOG(LogTemp, Warning, TEXT("box hp : %d"), maxHP)
	}
}

총알과 충돌하는지 확인도 해주고, HP가 잘 깎이는지도 확인하기 위해 로그를 남겼다.

bullet->attkScore의 변수는 어디서 나왔냐면, bullet의 헤더파일에 선언해준 변수이다.

int32 attkScore = 5;

 

05 위젯 클래스 만들기

	UPROPERTY(EditDefaultsOnly, meta = (BindWidget))
	class UProgressBar* hpBar;
	UPROPERTY(EditDefaultsOnly, meta = (BindWidget))
	class UTextBlock* txt_boxHP;

	void ShowHPBar(float hp, float maxhp);

hp가 채워져 있는 공간을 어떻게 계산하도록 할 것인지 하는 것이고,

그 값이 얼마인가 숫자도 표현해줄 것이다.

#include "Components/ProgressBar.h"
#include "Components/TextBlock.h"

void UItemBoxWidget::ShowHPBar(float hp, float maxhp)
{
	hpBar->SetPercent(maxhp / hp);
	txt_boxHP->SetText(FText::AsNumber(maxhp / hp * 10));
}

지금은 간단하게 progressbar을 사용하고 있지만 프로그래스바 이미지를 만들어서 직접 삽입할 수도 있다. 적용하는 방법은 동일하다. 이미지를 삽입하는건 SetSlate였던 것으로 기억한다.

다른 프로젝트를 할 당시 예쁘게라도 만들고 싶어서 모서리가 둥근 사각형 이미지를 만들어 넣어줬었다.

그리고 위젯을 사용한다면 Build.cs에 들어가 UMG 모듈을 추가해주면 된다.

이 부분을 볼 때마다 C#도 반드시 공부해야겠다는 생각이 든다.

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay", "EnhancedInput", "UMG" });

06 HP가 깎이는 부분과 위젯 클래스가 연결되도록

아이템박스 클래스의 Beginplay로 가서

boxWidget = Cast<UItemBoxWidget>(widgetComp->GetWidget());
if (boxWidget)
{
    boxWidget->ShowHPBar(hp, maxHP);
}

위젯클래스를 캐스팅한 후 hp 값을 계산하는 함수를 호출해준다.

widgetComp는 아이템박스에 있는 위젯 컴포넌트이고, boxWidget은 위젯 클래스이다.

728x90
반응형