3.ブループリントで C++ コードを拡張およびオーバーライドする

ブループリントを使用した C++ 機能の追加または置換

Windows
MacOS
Linux
On this page

このチュートリアルでは、 ブループリント を使用した C++ クラスの機能拡張方法を紹介します。ブループリントのチュートリアルとしてではなく、C++ コードの記述にミスがないことを確認するテストを目的としています。ブループリント の導入に関しては ブループリント クイックスタートガイド を一読することをお勧めします。

  1. "Countdown1" と名付けられた ACountdown インスタンスのビヘイビアを変更するには、まず編集可能な "Countdown1" の ブループリント バージョンをエディタで作成しなくてはいけません。これを行うには、ワールド アウトライナー で "Countdown1" を選択して [Details (詳細)] パネル[Blueprint/Add Script] ボタンをクリックします。

    AddScript.png

    ここで修正する ACountdown クラスを格納する Blueprint アセットにパスを割り当てて名前を付けることができます。

    SelectBlueprintPath.png

    "Countdown1" のブループリント バージョンを表す新規アセットが作成されます。"Countdown1" もこの新規ブループリントのインスタンスと置き換えられるため、ブループリントを変更するとゲーム内の "Countdown1" に影響を及ぼします。

  2. アンリアル エディタコンテンツ ブラウザ に表示される新規アセットへ自動的に移動します。アセットを 右クリック し、[Edit (編集) ...] を選択して、 Blueprint Graph (ブループリントグラフ)Component (コンポーネント) 階層、 Default Values (デフォルト値) を修正します。

    BlueprintInContentBrowser.png

    EditBlueprint.png

  3. 関数とイベントは イベントグラフ タブに表示されます。最初にこれを選択します。

    SelectEventGraph.png

    イベントグラフ ウィンドウの任意の場所を 右クリック して、ビヘイビアを決定するイベントノードとして CountdownHasFinished 関数を追加することができます。

    SelectEvent.png

  4. 新規ノードの右側にある白い (実行) ピンを左クリックしてドラッグし、機能を追加することができます。

    DragExecPin.png

    左マウス ボタンを放すと、実行したい関数またはイベント名の入力が促されます。このチュートリアルでは、カウントダウン終了時に パーティクル システム をスポーンしましょう。Spawn Emitter At Location ノードが必要なので、このノードをリストから選択します。例えば「spawn loc」など名前の一部を検索欄に入力すると時間を短縮できます。次に黄色の「Location」ピンを左クリックしてドラッグし、 Get Actor Location 関数にアタッチします。

    GetActorLocation.png

    後は作成したいエフェクトを選択するだけです。"Emitter Template" で "Select Asset" をクリックすると、適切なエフェクト アセットのリストを取得できます。この場合、"P_Explosion" が適切であるため、これを選択します。

    SelectParticle.png

  5. ブループリント エディタ の左上にある [Compile (コンパイル)] ボタンをクリックして変更を保存します。

  6. ここで [Play (再生)] を押すと、カウントダウンが始まり、カウントダウン数がゼロになると爆発します。

    Explosion_Zero.png

    しかし、カウントダウンは最後に「0」ではなく「GO!」となるようにプログラミングしました。C++ の機能を ブループリント ビジュアルスクリプティングに完全に置きかえたため、これはもう起こりません。この状況は意図したものではないため、この関数の C++ バージョンへの呼び出しを追加しなくてはいけません。Countdown Has Finished ノードを右クリックして、コンテキスト メニューから Add call to parent function を選択します。

    CallToParent_Menu.png

    この作業が終了すると Parent:Countdown Has Finished とラベル付けされたノードが イベントグラフ に配置されます。Parent ノードを接続する典型的な場所は、イベントノードへの直接接続です。Parent-call ノードはその他のノード同様に、何度でもどこからでも呼び出すことができるため、これは必須ではありません。

    CallToParent_ConnectPins.png

    これにより Spawn Emitter At Location への接続が置換されるため、 Parent:Countdown Has Finished ノードの右側 (出力) にある実行ピンを Spawn Emitter At Location に接続する必要があります。接続しなければ実行しません。

    CallToParent_FixPins.png

    これでゲームの実行時にカウントダウンが終了すると "GO!" (C++ コードから) という文字と爆発 (ブループリント グラフから) が表示されます。

    Explosion_Go.png

完成コード

Countdown.h

// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.

#pragma once

#include "GameFramework/Actor.h"
#include "Countdown.generated.h"

UCLASS()
class HOWTO_VTE_API ACountdown : public AActor
{
    GENERATED_BODY()

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

protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

public:
    // Called every frame
    virtual void Tick( float DeltaSeconds ) override;

    //How long, in seconds, the countdown will run
    UPROPERTY(EditAnywhere)
    int32 CountdownTime;

    UTextRenderComponent* CountdownText;

    void UpdateTimerDisplay();

    void AdvanceTimer();

    UFUNCTION(BlueprintNativeEvent)
    void CountdownHasFinished();
    virtual void CountdownHasFinished_Implementation();

    FTimerHandle CountdownTimerHandle;
};

Countdown.cpp

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

#include "HowTo_VTE.h"
#include "Components/TextRenderComponent.h"
#include "Countdown.h"

// Sets default values
ACountdown::ACountdown()
{
    // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = false;

    CountdownText = CreateDefaultSubobject<UTextRenderComponent>(TEXT("CountdownNumber"));
    CountdownText->SetHorizontalAlignment(EHTA_Center);
    CountdownText->SetWorldSize(150.0f);
    RootComponent = CountdownText;

    CountdownTime = 3;
}

// Called when the game starts or when spawned
void ACountdown::BeginPlay()
{
    Super::BeginPlay();

    UpdateTimerDisplay();
    GetWorldTimerManager().SetTimer(CountdownTimerHandle, this, &ACountdown::AdvanceTimer, 1.0f, true);
}

// Called every frame
void ACountdown::Tick( float DeltaTime )
{
    Super::Tick( DeltaTime );

}

void ACountdown::UpdateTimerDisplay()
{
    CountdownText->SetText(FString::FromInt(FMath::Max(CountdownTime, 0)));
}

void ACountdown::AdvanceTimer()
{
    --CountdownTime;
    UpdateTimerDisplay();
    if (CountdownTime < 1)
    {
        // We're done counting down, so stop running the timer.
        GetWorldTimerManager().ClearTimer(CountdownTimerHandle);
        //Perform any special actions we want to do when the timer ends.
        CountdownHasFinished();
    }
}

void ACountdown::CountdownHasFinished_Implementation()
{
    //Change to a special readout
    CountdownText->SetText(TEXT("GO!"));
}
Select Skin
Light
Dark

Welcome to the new Unreal Engine 4 Documentation site!

We're working on lots of new features including a feedback system so you can tell us how we are doing. It's not quite ready for use in the wild yet, so head over to the Documentation Feedback forum to tell us about this page or call out any issues you are encountering in the meantime.

We'll be sure to let you know when the new system is up and running.

Post Feedback