イベント ディスパッチャー / デリゲートのクイックスタート

イベント ディスパッチャー / デリゲート通信メソッドのクイックスタート

実装方法を選んでください。

Blueprints

C++

概要

イベント ディスパッチャーは、あるアクタがイベントをディスパッチし、それをリスニングしている別のアクタが通知を受けるようなアクタ通信手段です。

この方法を使い、通知を発信するアクタは、リスニングしているアクタがサブスクライブする イベント ディスパッチャー を作成します。この通信方法では、1 対多の関係を使用しており、作業アクタがイベント ディスパッチャーをトリガーし、リスニングしている多数のアクタが通知を受けます。 このクイック スタート ガイドでは、レベル内で 2 つのアクタをトリガーする OnBossDied イベントをデリゲート イベントで作成する方法を学習します。

設定

  1. [スターターコンテンツ] を有効にして、[Games (ゲーム)] > **[Third Person (サードパーソン)] > [Blueprint] の順に選択して、プロジェクトを作成します。

    ![](ProjectSetupBP.png)(w:600)

OnBossDiedEvent イベントを作成する

  1. コンテンツ ブラウザ**を右クリックして、[Create Basic Asset (基本アセットの作成)]** セクション内の [Blueprint Class (ブループリント クラス)] をクリックします。

    ![](BlueprintClass.png)

  1. [Actor (アクタ)] クラスを親クラスとして選択し、ブループリントに「BP_BossDied」という名前を付けます。

    ![](ParentClassActor.png)

  1. ブループリント エディタ内の [Viewport (ビューポート)] から [BP_BossDied] を開いて [Add Component (コンポーネントを追加)] ボタンをクリックし、「Box Collision」を検索して選択します。

    ![](BoxCollision.png)

  2. Box Collision」を選択した状態で、スケーリングを「X = 4」、「Y = 4」、「 Z = 2」に変更します。

    ![](TransformScale.png)

  1. Box Collision」を選択した状態で、[Details (詳細)] パネルの [Rendering (レンダリング)] セクションに異動し、[Hidden in Game (ゲーム内で非表示)] のチェックボックスを無効にします。これで、ゲームプレイ中にコリジョン ボックスが表示されます。

    ![](HiddenInGame.png)

  1. Box Collision」を右クリックして [Add OnComponentBeginOverlap (OnComponentBeginOverlap を追加)] を選択します。すると、ノードに イベント グラフ が表示されます。

    ![](BeginOverlapEvent.png)

  1. 左にある [My Blueprint (マイ ブループリント)] パネルから [Event Dispatchers (イベント ディスパッチャー)] セクションに移動し、[+ Add New (新規追加)] をクリックして新規イベントを追加します。このイベントに「OnBossDied」という名前を付けます。

    ![](BossDiedED.png)

  1. OnBossDiedイベント グラフ にドラッグし、[Call (コール)] を選択してノードを追加します。

    ![](CallBossDied.png)

  1. On Component Begin Overlap ノードを Call OnBossDied ノードに接続します。ブループリントを コンパイル して 保存 します。

    1. BP_BossDied ブループリントをレベルにドラッグします。

    ![](DragBossDied.png)(w:600)

インタラクティブなドアを作成する

  1. コンテンツ ブラウザ**を右クリックして、[Create Basic Asset (基本アセットの作成)]** セクション内の [Blueprint Class (ブループリント クラス)] をクリックします。

    ![](BlueprintClass.png)

  1. [Actor (アクタ)] クラスを親クラスとして選択し、ブループリントに「BP_BossDoor」という名前を付けます。

    ![](ParentClassActor.png)

  1. [Viewport (ビューポート)] から [BP_BossDoor] を開いて [Add Component (コンポーネントを追加)] のドロップダウンをクリックし、「Static Mesh」を検索して選択します。コンポーネントに「Frame」という名前を付けます。

    1. 別の Static Mesh コンポーネントを追加し、「Door」という名前を付けます。

  1. [Details (詳細)] パネルから、Frame コンポーネントを選択し、[Static Mesh (スタティック メッシュ)]のドロップダウンをクリックし、「SM_DoorFrame」を検索し、選択します。

    ![](SM_DoorFrame.png)

  1. Door コンポーネントに対しても上の手順を繰り返し、SM_Door スタティック メッシュを追加します。

    ![](SM_Door.png)

    1. Door コンポーネントを選択した状態で、以下のように Y の位置を「45」に設定します。すると、ドアが枠にぴったり合っている状態で表示されるはずです。

    ![](YLocation.png)

    1. [Event Graph (イベント グラフ)] を右クリックして、「Add Custom Event」を検索、選択します。イベントに「OpenDoor」という名前を付けます。

    ![](AddCustomEvent.png)

  1. OpenDoor ノードからイベントをドラッグして、「Add Timeline」 を検索、選択します。タイムラインの名前を 「TM_Door」 にします。

    ![](TM_Door.png)

  1. TM_Door をダブルクリックして開きます。[Add Float Curve (Float カーブを追加)] ボタンをクリックして、Float トラックを追加し、「Alpha」という名前を付けます。[Length (長さ)] を「1.0」に設定します。

    ![](AddFloatTrack.png)

  1. グラフを右クリックし、[Add key to CurveFloat_1 (CurveFloat_1 にキーを追加する)] を選択し、新しいポイントを追加します。[Time (時間)][Value (値)] を 「0.0」に設定します。

    ![](KeyPoints.png)

    1. 上の手順を繰り返して別のポイントを追加し、[Time (時間)][Value (値)] を 「1.0」に設定します。

  1. イベント グラフ に戻って Door Static Mesh コンポーネントを イベント グラフ にドラッグし、ノードを作成します。Door ノードからドラッグして、「SetRelativeRotation」を検索、選択します。

    ![](DoorRotation.png)

  1. TM_Door から Update ピンを接続し、SetRelativeRotation ノードにつなげます。New Rotation ピンを右クリックして「Split Struct Pin」を選択します。

    ![](SplitStructPin.png)

  1. イベント グラフ を右クリックして、「Lerp Float」を検索、選択します。[Return Value (戻り値)]SetRelativeRotation ノードの Yaw ピンに接続します。TM_DoorAlpha ピンを Lerp ノード上の Alpha に接続します。最後に、B の値を以下のように「90.0」に設定します。

    ![](Lerp.png)

  1. [Variable (変数)] セクションの横にある [+] ボタン**をクリックして新しい変数を追加します。この変数に「BossDiedReference**」という名前を付けます。

    ![](BossDiedRef.png)

  1. [Details (詳細)] パネルから、[Variable Type (変数の型)]のドロップダウンをクリックし、BP_BossDied の「Object Reference」を検索し、選択します。[Instance Editable (インスタンス編集可能)] チェックボックスをオンにします。

    ![](InstanceEditable.png)

    1. BossDiedReferenceイベント グラフ にドラッグして、Get BossDiedRerence を選択します。ノードからドラッグして、「Bind Event to On Boss Died」を検索、選択します。

    ![](BindEvent.png)

  1. Bind Event to On Boss Died の 赤い Event ピンからドラッグして 「Add Custom Event」を検索、選択します。イベントに「BossDied」という名前を付けます。

    ![](AddCustom.png)

  1. BossDied ノードからドラッグして、「Open Door」を検索、選択します。以下のように、Event Begin PlayBind Event to On Boss Died ノードに接続します。

    ![](EventPlay.png)

  1. ブループリントを コンパイル して 保存 します。

イベント ディスパッチャーをテストする

  1. BP_BossDoor アクタをレベルにドラッグします。[Details (詳細)]パネルに行き、[Boss Reference Died] のドロップダウンをクリックし、「BP_BossDied」を検索、選択します。

    ![](BossActorDrag.png)(w:600)

  1. [Play (プレイ)] を押して BP_BossDied に近づき、ゲーム内のボスが死ぬシミュレートをトリガーします。

    ![](EndResult.gif)(convert:false)

次のステップ

イベント ディスパッチャーの使用方法がわかりました。次は「Actor Communication 」のドキュメント ページで他の通信方法を見てみましょう。

概要

デリゲートは、型安全な方法でアクタ クラス ブループリント内の方法を呼び出すことができます。ダイナミックにバインドし、あるアクタがリスニングしている別のアクタにイベントをトリガーして通信を確立することができます。 このクイック スタート ガイドでは、レベル内で 2 つのアクタ クラス ブループリントをトリガーする OnBossDied イベントをデリゲートで作成する方法を学習します。

詳細なドキュメントについては、デリゲート を参照してください。

必要な設定

  1. [Games (ゲーム)] > **[Third Person (サードパーソン)] > [C++] の順に選択して、[スターターコンテンツ] を有効にしてプロジェクトの作成を開始します。

    ![](ProjectSetupCpp.png)(w:600)

Boss アクタと OnBossDied デリゲートを作成する

  1. C++ クラス ウィザード から、新規アクタクラスを「BossActor」という名前で作成します。

    ![](AddActorCpp.png)(w:600)

  2. BossActor.h へ移動します。ライブラリ インクルードで以下のデリゲートを宣言します。

    DECLARE_DELEGATE(FOnBossDiedDelegate);
  3. クラス デフォルトに以下を宣言します。

    protected:
        UFUNCTION()
        void HandleBossDiedEvent();
        UPROPERTY(EditInstanceOnly, BlueprintReadWrite)
        class UBoxComponent* BoxComp;
        virtual void NotifyActorBeginOverlap(AActor* OtherActor);
    
    public:
        FOnBossDiedDelegate OnBossDied;
  4. BossActor.cpp に移動し、次のクラス ライブラリを追加します。

    #include "Components/BoxComponent.h"
  5. 次のクラス定義を実装します。

    ABossActor::ABossActor()
    {
        BoxComp = CreateDefaultSubobject<UBoxComponent>(TEXT("BoxComp"));
        BoxComp->SetBoxExtent(FVector(128, 128, 64));
        BoxComp->SetVisibility(true);
    }
    
    void ABossActor::HandleBossDiedEvent()
    {
        OnBossDied.ExecuteIfBound();
    }
    
    void ABossActor::NotifyActorBeginOverlap(AActor* OtherActor)
    {
        HandleBossDiedEvent();
    }
  6. コードを コンパイル します。

  7. C++ Classes」フォルダで BossActor アクタを右クリックし、[C++ Class Actions] ドロップダウン メニューから [Create Blueprint class based on BossActor] を選択します。ブループリントに「BP_BossActor」と名前を付けます。

    ![](BossActor.png)(w:600)

  8. BossActor のインスタンスをレベルにドラッグします。

    ![](BossActorDrag.png)(w:600)

完成コード

BossActor.h

#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "BossActor.generated.h"

DECLARE_DELEGATE(FOnBossDiedDelegate);
UCLASS()

class BPCOMMUNICATION_API ABossActor : public AActor
{
    GENERATED_BODY()

public: 

    // Sets default values for this actor's properties
    ABossActor();

protected:

    // Called when the game starts or when spawned
    virtual void BeginPlay() override;
    UFUNCTION()
    void HandleBossDiedEvent();
    UPROPERTY(EditInstanceOnly, BlueprintReadWrite)
    class UBoxComponent* BoxComp;
    virtual void NotifyActorBeginOverlap(AActor* OtherActor);

public: 

    // Called every frame
    virtual void Tick(float DeltaTime) override;
    FOnBossDiedDelegate OnBossDied;
};

BossActor.cpp

#include "BossActor.h"
#include "Components/BoxComponent.h"
#include "BPCommunicationGameMode.h"

// Sets default values
ABossActor::ABossActor()
{
    // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;
    BoxComp = CreateDefaultSubobject<UBoxComponent>(TEXT("BoxComp"));
    BoxComp->SetBoxExtent(FVector(128, 128, 64));
    BoxComp->SetVisibility(true);
}

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

void ABossActor::HandleBossDiedEvent()
{
    OnBossDied.ExecuteIfBound();
}

void ABossActor::NotifyActorBeginOverlap(AActor* OtherActor)
{
    HandleBossDiedEvent();
}

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

インタラクティブなドアを作成する

  1. C++ クラス ウィザード で、新規 Actor クラスを「DoorActor」という名前で作成します。

  2. 「DoorActor.h」ファイルに移動し、次のように宣言します。

    include "Components/TimelineComponent.h"

  3. 次に、以下のクラスを宣言します。

    // Variable to hold the Curve asset
        UPROPERTY(EditInstanceOnly)
        UCurveFloat* DoorTimelineFloatCurve;
    
    protected:
    
        void BossDiedEventFunction();
        UPROPERTY(EditInstanceOnly,BlueprintReadWrite)
        class ABossActor* BossActorReference;
    
        //MeshComponents to represent Door assets
        UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
        UStaticMeshComponent* DoorFrame;
        UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
        UStaticMeshComponent* Door;
    
        //TimelineComponent to animate Door meshes
        UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
        UTimelineComponent* DoorTimelineComp;
    
        //Float Track Signature to handle our update track event
        FOnTimelineFloat UpdateFunctionFloat;
    
        //Function which updates our Door's relative location with the timeline graph
        UFUNCTION()
        void UpdateTimelineComp(float Output);
  4. DoorActor.cpp」内に、次のクラス ライブラリを宣言します。

    #include "BossActor.h"
  5. 次のクラス定義を実装します。

    ADoorActor::ADoorActor()
    {
        //Create our Default Components
        DoorFrame = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("DoorFrameMesh"));
        Door = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("DoorMesh"));
        DoorTimelineComp = CreateDefaultSubobject<UTimelineComponent>(TEXT("DoorTimelineComp"));
    
        //Setup our Attachments
        DoorFrame->SetupAttachment(RootComponent);
        Door->AttachToComponent(DoorFrame, FAttachmentTransformRules::KeepRelativeTransform);
        Door->SetRelativeLocation(FVector(0, 35, 0));
    }
    
    // Called when the game starts or when spawned
    void ADoorActor::BeginPlay()
    {
        Super::BeginPlay();
    
        //Binding our float track to our UpdateTimelineComp Function's output
        UpdateFunctionFloat.BindDynamic(this, &ADoorActor::UpdateTimelineComp);
    
        //If we have a float curve, bind it's graph to our update function
        if (DoorTimelineFloatCurve)
        {
            DoorTimelineComp->AddInterpFloat(DoorTimelineFloatCurve, UpdateFunctionFloat);
        }
    
        if (BossActorReference)
        {
        BossActorReference->OnBossDied.BindUObject(this, &ADoorActor::BossDiedEventFunction);
        }
    }
    
    void ADoorActor::BossDiedEventFunction()
    {
        DoorTimelineComp->Play();
    }
    
    void ADoorActor::UpdateTimelineComp(float Output)
    {
        // Create and set our Door's new relative location based on the output from our Timeline Curve
        FRotator DoorNewRotation = FRotator(0.0f, Output, 0.f);
        Door->SetRelativeRotation(DoorNewRotation);
    }
  6. コードをコンパイルします。

  7. コンテンツ ブラウザ[Add/Import] > [Miscellaneous] > [Curve] を選択します。

    ![](MiscCurve.png)

  8. [CurveFloat] を選択して CurveFloat アセットに「DoorCurveFloat」という名前を付け、DoorCurveFloat アセットをダブルクリックします。2 つのキーを Float カーブに追加し、1 つのキーに時間の値「(0,0)」を、もう 1 つ のキーに時間の値「(4,90)」を割り当てます。

    ![](DoorCurveFloat.png)(w:600)

  9. Shift キーを押しながら 2 つのキーを選択して Auto Cubic interpolation に設定し、カーブを保存します。

    ![](AutoCubic.png)(w:600)

  10. DoorCurveFloat を保存します。

  11. コンテンツ ブラウザから「C++ Classes」フォルダに移動して DoorActor クラスを右クリックし、[Create Blueprint Class based on Door Actor] を選択します。ブループリント アクタに「BP_DoorActor」という名前を付けます。

    ![](BP_Door.png)(w:600)

  12. BP_DoorActor[Class Defaults (クラスのデフォルト)] 内で[Components (コンポーネント)] タブを探し、DoorFrame Static Mesh コンポーネント を選択して [Details (詳細)] パネルに移動して [Static Mesh (スタティック メッシュ)]を「SM_DoorFrame」に変更します。

    ![](SM_DoorFrame.png)(w:600)

  13. [Components (コンポーネント)] パネルで DoorMesh コンポーネントを選択します。[Details] パネルに移動し、スタティックメッシュを SM_Door に変更します。

    ![](SM_Door.png)(w:600)

  14. [Details (詳細)] パネルの [DoorCurveFloat] から [DoorCurveFloat] を選択します。

    ![](CurveDetail.png)(w:600)

  15. ブループリントを コンパイル して 保存 します。

完成コード

DoorActor.h

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/TimelineComponent.h"
#include "DoorActor.generated.h"

UCLASS()
class BPCOMMUNICATION_API ADoorActor : public AActor
{   
    GENERATED_BODY()

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

    // Variable to hold the Curve asset
    UPROPERTY(EditInstanceOnly)
    UCurveFloat* DoorTimelineFloatCurve;

protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;
    void BossDiedEventFunction();
    UPROPERTY(EditInstanceOnly,BlueprintReadWrite)
    class ABossActor* BossActorReference;

    //MeshComponents to represent Door assets
    UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
    UStaticMeshComponent* DoorFrame;
    UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
    UStaticMeshComponent* Door;

    //TimelineComponent to animate Door meshes
    UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
    UTimelineComponent* DoorTimelineComp;

    //Float Track Signature to handle our update track event
    FOnTimelineFloat UpdateFunctionFloat;

    //Function which updates our Door's relative location with the timeline graph
    UFUNCTION()
    void UpdateTimelineComp(float Output);

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

DoorActor.cpp

#include "DoorActor.h"
#include "BossActor.h"

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

    //Create our Default Components
    DoorFrame = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("DoorFrameMesh"));
    Door = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("DoorMesh"));
    DoorTimelineComp = CreateDefaultSubobject<UTimelineComponent>(TEXT("DoorTimelineComp"));

    //Setup our Attachments
    DoorFrame->SetupAttachment(RootComponent);
    Door->AttachToComponent(DoorFrame, FAttachmentTransformRules::KeepRelativeTransform);
    Door->SetRelativeLocation(FVector(0, 35, 0));
}

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

    //Binding our float track to our UpdateTimelineComp Function's output
    UpdateFunctionFloat.BindDynamic(this, &ADoorActor::UpdateTimelineComp);

    //If we have a float curve, bind its graph to our update function
    if (DoorTimelineFloatCurve)
    {
        DoorTimelineComp->AddInterpFloat(DoorTimelineFloatCurve, UpdateFunctionFloat);
    }
if (DoorTimelineFloatCurve)
    {
        BossActorReference->OnBossDied.BindUObject(this, &ADoorActor::BossDiedEventFunction);
    }
}

void ADoorActor::BossDiedEventFunction()
{
    DoorTimelineComp->Play();
}

void ADoorActor::UpdateTimelineComp(float Output)
{
    // Create and set our Door's new relative location based on the output from our Timeline Curve
    FRotator DoorNewRotation = FRotator(0.0f, Output, 0.f);
    Door->SetRelativeRotation(DoorNewRotation);
}

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

5 - イベント ディスパッチャーをテストする

  1. BP_Door ブループリントをレベルにドラッグします。[Details(詳細)]パネルに行き、[Boss Reference Died] のドロップダウンをクリックし、BP_BossDied を検索し、選択します。

    ![](BossActorDrag.png)(w:600)

  2. Bp_DoorActor を選択した状態で、[Details (詳細)] パネルに移動し、[Boss Actor Reference (ボス アクタ参照)] ドロップダウンの矢印をクリックして、「BP_BossActpr」を検索して選択します。

  3. [Play (プレイ)] を押して BP_BossActor に近づき、ゲーム内のボスが死ぬシミュレートをトリガーします。

    ![](EndResult.gif)

次のステップ

デリゲートの使い方が分かったところで、今度は「アクタ通信」ドキュメント ページで参照されている他の通信手段を見てみましょう。

このページは Unreal Engine の前のバージョン用です。現在リリースされている Unreal Engine 5.1 に対して更新は行われていません。
Unreal Engine のドキュメントを改善するために協力をお願いします!どのような改善を望んでいるかご意見をお聞かせください。
調査に参加する
キャンセル