GameProgrammar's Night

ゲームプログラム系の覚え書き

UE4 C++でイベント/イベントディスパッチャーを作る

 UE C++には、デリゲートが用意されています。デリゲートとは簡単に説明しますと、メソッド・関数などを変数に保存して、任意のタイミングで呼び出せる仕組みです。詳しくはググってください。

docs.unrealengine.com

 このデリゲートの中に、BP上でイベント/イベントディスパッチャーとして扱われる仕組みがありますので紹介します。

イベントディスパッチャー

 良く使うであろうイベントディスパッチャーの実装から先に説明します。
 動的マルチキャストデリゲートを実装するとBP上ではイベントディスパッチャーとして扱われます。

docs.unrealengine.com

実装例

// 動的マルチキャストデリゲート(イベントディスパッチャー)の宣言
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FMyActorOnEventDispather);

UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class UMyActorComponent : public UActorComponent
{
    GENERATED_BODY()

    virtual void TickComponent( float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction ) override;

public:
   // 動的マルチキャストデリゲート(イベントディスパッチャー)の定義
   UPROPERTY(BlueprintAssignable, Category="MyActor")
   FMyActorOnEventDispather OnEventDispather;
};

void UMyActorComponent::TickComponent( float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction )
{
   OnEventDispather.Broadcast(); // イベントディスパッチャーをCallする
}

 DECLARE_DYNAMIC_MULTICAST_DELEGATEマクロを使って、イベントディスパッチャー用のクラスを作ります。()の中がクラス名となります。
 その作ったクラスのプロパティをクラス内で定義し、Assingnableに設定します。そうすることでBPで作ったイベントをバインドすることができます。
イベントディスパッチャーとして宣言した変数のBroadcastメソッドを呼ぶことが、イベントディスパッチャーをCallすることと同じことになります。

 BP上でMyActorComponentをActorに追加して、使った例は以下の通り。
f:id:katze_7514:20160522001504j:plain
 イベントディスパッチャーとして使用できています。

 また、イベントディスパッチャーで引数を取る場合は、引数ありの宣言マクロを使います。

// 1つ引数を取り、型がboolで引数名がbSuccess のイベントディスパッチャー宣言
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMyActorOnEventDispather, bool, bSuccess);

 引数は8個まで取ることができます。引数の数を増やしたら、OneParamのOneの部分を引数の数の英語に変えます*1
 戻り値はBPのイベントディスパッチャー同様に扱えません。

イベント

 BPでのイベントに相当するのは、動的デリゲートです。デリゲートの中にイベントもありますが別ものです。名称がまぎらわしいですね。
docs.unrealengine.com

実装例

 実装の仕方は、動的マルチキャストとほぼ同じです。
 DECLARE_DYNAMIC_MULTICAST_DELEGATEマクロではなく、DECLARE_DYNAMIC_DELEGATEを使います。

// 動的デリゲート(イベント)の宣言
DECLARE_DYNAMIC_DELEGATE(FMyActorOnEvent);

UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class UMyActorComponent : public UActorComponent
{
    GENERATED_BODY()

   // BPから動的デリゲート(イベント)を呼び出すメソッド
   UFUNCTION(BluprintCallable, Category="MyActor")
   void CallOnEvent();

public:
   // 動的デリゲート(イベント)の定義
   UPROPERTY(BlueprintReadWrite, Category="MyActor")
   FMyActorOnEvent OnEvent;
};

void UMyActorComponent::CallOnEvent()
{
   OnEvent.ExecuteIfBound();
}

 イベントディスパッチャー実装と違うのは、イベントとして宣言した変数にBlueprintAssignableが使えません。代わりに通常の変数と同じようにBluprintReadWrite・BlueprintReadOnlyなどを使います。
 また、イベントの呼び出しは、Execute・ExecuteIfBoundメソッドのどちらかを使いますが、それらのメソッドはBPから直接呼ぶことができませんので、BP上から呼べるようにメソッド(CallOnEventメソッド)を別途追加します。
 BlueprintReadWriteで宣言すると、BP上のイベントをバインドできるようになります。また、イベントディスパッチャーにバインドすることも可能です。

f:id:katze_7514:20160522012117j:plain

 引数を取る時も、イベントディスパッチャー実装と同じです。

DECLARE_DYNAMIC_DELEGATE_OneParam(FMyActorOnEvent, bool, bSuccess);

*1:2個ならTwoなど