LoginSignup
0
0

More than 1 year has passed since last update.

[UE4] ブロック崩しを作る #6 スコアUI (C++)

Last updated at Posted at 2022-02-03

はじめに

この記事は UE4 でブロック崩しを作るシリーズ の続きになります。
今回はゲームにスコアを表示する UI を追加します。
UI の表示には UMG (Unreal Motion Graphics) を使用しますが、表示処理には BP のイベントグラフは使わず C++ で実装してゆきます。

完成ゲーム

image.png

環境

Windows 10
Unreal Engine 4.27.1
エディタ言語 英語

目次

スコア表示用の WBP を作成
WBP を操作する UUserWidget(C++) の作成
WBP と UUserWidget(C++) を繋げる
WBP を配置
実行
次回
おまけ

スコア表示用の WBP を作成

スコアを表示する WBP(Widget Blueprint) を作成します

Content Browser で右クリック
開いたメニューから User Interface → 「Widget Blueprint」を選択
image.png

作成された NewWidgetBlueprint を「WBP_Score」にリネームします
image.png

WBP 編集

「WBP_Score」をダブルクリックして BP 編集画面を開きます。
下記の UMG UI デザイナ が開きます
image.png

左にある Palette から「Text」を選択してメインのビューにドラッグ&ドロップ
この UI にテキスト表示が追加されます
image.png

追加したテキストの内容を編集します
image.png

  • 一番上の TextBlock_0 はデフォルトでつけられたこのテキストアイテムの名前です
  • 位置を左上に変更します。画面上でドラッグして移動も出来ます
  • 表示する内容を「SCORE 0」に変更します
  • フォントサイズを 50 くらいにしておきます

WBP を操作する UUserWidget(C++) の作成

上部メニューから File → New C++ Class.. を選択
開いたウィンドウから
① 右上の Show All Classes にチェックを入れ
UUserWidget を検索して選択
③ Next をクリック
image.png

名前を「UW_Score」として Create Class をクリック
Visual Studio が起動して プロジェクトに UW_Score.h /.cpp が追加されています

UUserWidget(C++) 編集

作成された UW_Score.h / .cpp を編集します

UW_Score.h
#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "Components/TextBlock.h" // 追加
#include "UW_Score.generated.h"

UCLASS()
class BREAK_BLOCK_API UUW_Score : public UUserWidget
{
    GENERATED_BODY()

protected:
    UTextBlock* m_pTextBlock;

public:
    UUW_Score(const FObjectInitializer& ObjectInitializer);

protected:
    virtual void NativeOnInitialized() override;

public:
    void UpdateScore(int score);
};
  • UTextBlock* m_pTextBlock を追加
    • 使う度に取得する必要のないように WBP に追加したテキスト表示のポインタを記録する変数
  • コンストラクタ 追加
  • void NativeOnInitialized() を override;
    • 初期化時に呼ばれるので、初期化用に使用
  • void UpdateScore(int score) を追加
    • 外部からスコアをセットしてもらいその数値に表示を更新する関数
UW_Score.cpp
#include "UW_Score.h"

// コンストラクタ
UUW_Score::UUW_Score(const FObjectInitializer& ObjectInitializer)
    : UUserWidget(ObjectInitializer)
    , m_pTextBlock(nullptr)
{
}

// 初期化、Text へのポインタを記録
void UUW_Score::NativeOnInitialized()
{
    Super::NativeOnInitialized();

    UTextBlock* pTextBlock = Cast<UTextBlock>(GetWidgetFromName("TextBlock_0"));
    ensure(pTextBlock != nullptr);
    m_pTextBlock = pTextBlock;
}

// スコアUI の Text を更新
void UUW_Score::UpdateScore(int score)
{
    FString str = TEXT("Score") + FString::FromInt(score);
    ensure(m_pTextBlock != nullptr);
    if(m_pTextBlock)
    {
        m_pTextBlock->SetText(FText::FromString(str));
    }
}
  • void NativeOnInitialized()
    • テキストの名前を TextBlock_0 にしていたので、その名前でテキストを取得
    • 毎回取得する必要のないように m_pTextBlock に保存
  • void UpdateScore(int score)
    • m_pTextBlock のテキスト表示を更新するには FText の文字列をセットする必要がある
    • FText は文字列の加工処理が苦手なので、一旦 FString で文字列を加工して最後に変換してセットしている

WBP と UUserWidget(C++) を繋げる

  • WBP_Score の編集画面を開きます
  • 右上の「Graph」を選択します
  • 上部の「Class Settings」を選択します
  • Details から Parent Class を「UW_Score」に変更します

image.png

WBP を配置

WBP を配置するには誰かが CreateWidget で実体を作り AddToViewport で画面に表示させる必要があります。今回はそれを行う専用の「Actor」を作成し、WBP が配置されるようにします。

WBP を配置する Actor を作成

  • 上部メニューから File → New C++ Class.. を選択
  • Actor を選択して Next をクリック
  • Name を「AUWScoreController」として Create Class をクリック
  • Visual Studio を reload して「AUWScoreController.h / .cpp」が追加されているのを確認

WBP を配置する Actor の編集

AUWScoreController.h / .cpp を編集します

AUWScoreController.h
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "UW_Score.h" // 追加
#include "AUWScoreController.generated.h"

UCLASS()
class BREAK_BLOCK_API AAUWScoreController : public AActor
{
    GENERATED_BODY()

public: 
    // Sets default values for this actor's properties
    AAUWScoreController();

protected:
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UMG_Game")
    TSubclassOf<UUserWidget> WBP_Score;

    UUW_Score* m_pUWScore;

    // Called when the game starts or when spawned
    virtual void BeginPlay() override;
    :
  • TSubclassOf WBP_Score を追加
    • 作成する UUserWidget を 編集画面から受け取る用
  • UUW_Score* m_pUWScore を追加
    • 配置した UMG のポインタを保存する
AUWScoreController.cpp
:
// Called when the game starts or when spawned
void AAUWScoreController::BeginPlay()
{
    Super::BeginPlay();

    m_pUWScore = CreateWidget<UUW_Score>(GetWorld(), WBP_Score);
    ensure(m_pUWScore);
    if (m_pUWScore)
    {
        m_pUWScore->AddToViewport();
    }
}
  • WBP_Score には作成すべき UUserWidget が指定されている前提で CreateWidget() で Widget を作成
  • 作成した widget を AddToViewport で表示

これで WBP を配置する Actor が作成できました
この Actor を配置すれば BeginPlay() が呼ばれ WBP が表示されます

WBP を配置する Actor を配置

Contents Browser を C++ Classes → BreakBlock の表示に切り替え
中にいる AUWScoreController をビューポートにドラッグ&ドロップで配置します
image.png

World Outliner に AUWScoreController が追加されています
それを選択して Details から WBP_Score をセットします
image.png
※ この Actor の .h に下記を追加していたので、このように Details から値をセットする事が可能です

UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UMG_Game")
TSubclassOf<UUserWidget> WBP_Score;

実行

プレイをするとゲーム画面左上にスコアが表示されるようになりました。

image.png

値の変化

この表示を変化させる UpdateScore(int score) を UUW_Scoreクラスに作成しましたが
まだ誰もこの関数を呼んでいませんでした。
下記のように AAUWScoreControllerクラス から関数を呼ぶようにします。

AUWScoreController.cpp
void AAUWScoreController::BeginPlay()
{
    :
    if (m_pUWScore)
    {
        m_pUWScore->AddToViewport();
        m_pUWScore->UpdateScore(30); // 追加
    }
}

表示されるテキストが「Score30」に変化しました
image.png

次回

スコアUIが表示されるようになりました。
ただ、ブロックを破壊してスコアが加算される、という処理ができておりません。
次回はその処理を作成してスコアUIを完成させます。

おまけ

UMG を C++ から 配置、操作する方法を書きましたが、下記の方法も使うことが出来るようです。

BindWidget

UUW_Scoreクラスで、テキスト表示のポインタを取得するのに下記の様なコードを書きましたが

UUW_Score.cpp

void UUW_Score::NativeOnInitialized()
{
    :
    m_pTextBlock = Cast<UTextBlock>(GetWidgetFromName("TextBlock_0"));
}

.h で下記のようにしておくと、この GetWidgetFromName のくだりは不要に出来るようです。

UUW_Score.h
    UPROPERTY(EditAnywhere, meta = (BindWidget))
    class UTextBlock* TextBlock_0 = nullptr;
  • .h で m_pTextBlock の代わりに下記の変数を作成
    • 変数名は WBP でテキストにつけた名前 TextBlock_0 を使う必要がある
  • .cpp で初期化せずとも TextBlock_0 を使う事ができる

参考リンク

この方法については下記から知る事ができました。

LoadSynchronous

WBP を配置する Actor に WBP を渡すのに Details からセットしましたが
image.png

下記のように .cpp からもセットできるようです

void AAUWScoreController::BeginPlay()
{
    Super::BeginPlay();

    //>>> 追加
    FString path = "/Game/WBP_Score.WBP_Score_C";
    TSubclassOf<class UUserWidget> WidgetClass;
    WidgetClass = TSoftClassPtr<UUserWidget>(FSoftObjectPath(path)).LoadSynchronous();  
    //<<< 追加

    m_pUWScore = CreateWidget<UUW_Score>(GetWorld(), WidgetClass);
    ensure(m_pUWScore);
    if (m_pUWScore)
    {
        m_pUWScore->AddToViewport();
    }
}
  • Content に置いた WBP_Score を読み込む
    • /Content の代わりに /Game を使う
    • WBP_Score という名前にしたので WBP_Score.WBP_Score_C を使う

参考リンク

この方法については下記の記事から知る事ができました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0