ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 블루아카이브 루트슈터 팬게임 프로젝트(8) - 적 체력바
    루트슈터 프로젝트 2024. 1. 4. 19:56

     

    루트슈터 게임을 할 때 적에게 명중하면 적의 바로 머리 위에 적의 체력바와 레벨 등의 대략적인 정보가 보입니다. 이번에는 이것을 구현해보겠습니다. 

     

     

    EnemyHPBarWidget.h

    UCLASS()
    class PROJECTBLUELANDS_API UEnemyHPBarWidget : public UUserWidget
    {
        GENERATED_BODY()


    public:
        UPROPERTY(BlueprintReadWrite, meta=(BindWidget))
        TObjectPtr<class UTextBlock> EnemyName;
        UPROPERTY(BlueprintReadWrite, meta=(BindWidget))
        TObjectPtr<class UTextBlock> EnemyLevel;
        UPROPERTY(BlueprintReadWrite, meta=(BindWidget))
        TObjectPtr<class UProgressBar> EnemyHPBar;

        void Init(FText name, int32 level); //정보 초기화
        void RefreshHP(float hpPercent); //데미지 받았을때 HP 초기화
        void SetInvisible();

        FTimerHandle hpBarTimerHandle;
    };

     

    먼저 체력바를 담당하는 새로운 위젯을 만듭니다. 적의 이름, 레벨, 체력상태를 표현하는 오브젝트들을 넣을 계획이고요, Init 함수는 처음에 적이 생성됐을때 적의 정보를 받아 초기화 하는 함수이고, RefreshHP함수는 데미지를 받았을때 HP바의 퍼센티지를 수정하는 함수입니다. SetInvisible은 위젯을 숨기게 하기 위한 단순한 함수입니다. 

     

     

     

    EnemyHPBarWidget.cpp

     

    void UEnemyHPBarWidget::Init(FText name, int32 level)
    {

        EnemyName->SetText(name);
        FString temp = FString::FromInt(level);
        EnemyLevel->SetText(FText::FromString(temp));
        EnemyHPBar->SetPercent(1.0);
        SetVisibility(ESlateVisibility::Hidden);
    }

    void UEnemyHPBarWidget::RefreshHP(float nowHPPercent)
    {
        EnemyHPBar->SetPercent(nowHPPercent);
        this->SetVisibility(ESlateVisibility::Visible);
       
        GetWorld()->GetTimerManager().SetTimer(hpBarTimerHandle, this, &UEnemyHPBarWidget::SetInvisible, 2.0f, false);
    }

    void UEnemyHPBarWidget::SetInvisible()
    {
        this->SetVisibility(ESlateVisibility::Hidden);
    }

     

    cpp 파일은 단순합니다. Init 함수는 적에게 정보를 받아 초기화 하고, RefreshHP는 남은 체력의 퍼센티지를 받아서 초기화 해주면 됩니다. RefreshHP가 호출됐다는 것은 데미지를 받았다는 것이므로 이 위젯을 보이도록 Visible로 바꿔줍니다(기본 Hidden으로 설정해놨습니다.)

    그리고 타이머로 2초의 유예를 두고 그 후에 위젯을 숨기면 됩니다. 

     

     

    EnemyCharacter.h

    public:
        UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
        class UWidgetComponent* hpBarComponent;

     

    적 캐릭터을 표현하는 제일 기본 클래스의 헤더파일에 위젯 컴포넌트를 초기화해줍니다. 이때 블루프린트에서 읽기 쓰기가 가능하도록 UPROPERTY에 BlueprintReadWrite를 추가해줍니다. 

     

     

    EnemyCharacter.cpp

     

    AEnemyCharacter::AEnemyCharacter()
    {
        hpBarComponent = CreateDefaultSubobject<UWidgetComponent>(TEXT("HP Bar Widget Component"));
        hpBarComponent->SetupAttachment(RootComponent);
    }
    void AEnemyCharacter::BeginPlay()
    {
        Super::BeginPlay();

        UEnemyHPBarWidget* temp = Cast<UEnemyHPBarWidget>(hpBarComponent->GetWidget());
        if(temp)
        {
            temp->Init(enemyName, enemyLevel);
        }
    }

     

    BeginPlay함수는 적이 스폰되고 바로 호출되므로 이곳에서 적이 가지는 체력바 위젯을 초기화 해주면 됩니다. 

     

     

    HealthComponent.cpp

     

    void UHealthComponent::DamageTaken(AActor* damagedActor, float Damage, const UDamageType* damageType, AController* instigator, AActor* damageCauser)
    {
        if (Damage <= 0.0f) return;
        nowHealth -= Damage;

        if(AEnemyCharacter* enemy = Cast<AEnemyCharacter>(damagedActor))
        {
            UEnemyHPBarWidget* temp = Cast<UEnemyHPBarWidget>(enemy->hpBarComponent->GetWidget());
            temp->RefreshHP(nowHealth / maxHealth);
        }

        if(nowHealth <= 0.0f && bluelandsGameMode) bluelandsGameMode->ActorDied(damagedActor);
        UE_LOG(LogTemp, Display, TEXT("%f"), nowHealth);
    }

     

    제가 생각해보니 체력을 담당하는 컴포넌트에 대해서는 포스팅 한 적이 없는 것 같습니다. 이 함수는 이 컴포넌트를 가진 액터가 데미지를 받으면 발동되는 함수입니다. 여기서 적이 데미지를 입었다면 RefreshHP 함수로 새로고침 해주면 됩니다. 

     

     

    이번에 만든 체력바 클래스를 기반으로 생성한 블루프린트입니다. 체력바 위에 레벨과 적 이름이 같이 적혀있는 방식입니다. 여기서 중요한 것은 유저 인터페이스의 스페이스를 Screen으로 바꾼 후 체력바 UI와 UI의 앵커를 전부 캔버스패널의 정중앙에 둬야 합니다. 그래야 적 머리위에 고정됩니다. 

     

     

     

    적의 블루프린트에 아까 선언한 위젯 컴포넌트의 위젯 클래스로 위의 체력바 위젯 블루프린트를 넣어주면 됩니다. 

     

     

     

     

     

     

    결과물입니다. 적에게 피해를 주면 체력바UI가 켜지고 2초 기다리면 사라집니다. 이제 뭔가 점점 게임스럽게 보여지고 있습니다. 뭔가 뿌듯하네요 

     

    이만 줄이겠습니다. 다음에는 플레이어의 정보들을 화면에 띄울 수 있도록 해야겠습니다. 감사합니다. 

     

     

Designed by Tistory.