この記事はUnreal Engine 4(UE4) Advent Calendar 2019の6日目の投稿記事です。
目的
UE4 EditorでC++のソースをコンパイルした際の通知をDiscordで受け取りたい。
やっていくこと
- 空のプラグインを作成する
-
HTTP
,Json
をPrivateDependencyModuleNames
に追加 - イベントリスナを作成し、DiscordにWebhookリクエストをかけられるようにする
-
IHotReloadInterface
のOnModuleCompilerFinished
にイベントリスナをバインドする
やっていく
Discord Webhook URLの取得
Discordで任意のチャンネルにWebhookを作成します。
任意の名前やアイコンを設定し、「ウェブフックURL」をコピーしておきます。
このURLがプラグインからのリクエストに必要になります。
空のプラグイン作成
Editor -> Plugins -> New Plugins より適当な名前を設定し、プラグインを作成します。
この記事では HotReloadNotifications
という名前で設定して進めていきます。
必要なモジュールの依存を追加
Visual Studio を起動して、HotReloadNotificationsModule.Build.cs
を編集します。
PrivateDependencyModuleNames
に HTTP
と Json
を追記します。
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"HTTP",
"Json"
// ... add private dependencies that you statically link with here ...
}
);
HTTP
は Webhookの送信に必須で、 Json
はDiscord Webhookで送信するJson文字列の生成にあると便利です。
イベントリスナの定義を作成する
HotReloadNotificationsModule.h
を開き、引数が (const FString&, ECompilationResult::Type, bool)
なメンバ関数を用意します。
void OnCompileFinished(const FString& LogDump, ECompilationResult::Type CompilationResult, bool bShowLog) const;
なお、 ECompilationResult::Type
を使用するために Misc/CompilationResult.h
をインクルードする必要があります。
#include "Misc/CompilationResult.h"
実装
続いて、 HotReloadNotificationsModule.cpp
を編集していきます。
ヘッダのインクルード
HttpModule.h
, Interfaces/IHttpRequest.h
, Serialization/JsonSerializerMacros.h
, Misc/HotReloadInterface.h
の4ファイルをインクルードします。
#include "HttpModule.h" // -> HTTP Request
#include "Interfaces/IHttpRequest.h" // -> HTTP Request
#include "Serialization/JsonSerializerMacros.h" // Serialize Struct
#include "Misc/HotReloadInterface.h" // -> Listen HotReload Event
イベントリスナのバインド
IHotReloadInterface | Unreal Engine Documentation
今回はこの IHotReloadInterface
より FModuleCompilerFinishedEvent
にイベントをバインドして機能を作ります。
IHotReloadInterface
のインスタンスを静的な関数 GetPtr()
から取得します。
const auto& HotReloadModule = IHotReloadInterface::GetPtr();
FModuleCompilerFinishedEvent
はメンバ関数 OnModuleCompilerFinished
より取得できます。
Eventに AddRaw
してバインドは完了です。
HotReloadModule->OnModuleCompilerFinished().AddRaw(this, &FHotReloadNotificationsModule::OnCompileFinished);
Webhook送信する構造体の作成
struct FDiscordWebhookRequestBody : public FJsonSerializable
{
FString Content;
BEGIN_JSON_SERIALIZER
JSON_SERIALIZE("content", Content);
END_JSON_SERIALIZER
FDiscordWebhookRequestBody(const FString& Content) : Content(Content) {}
FDiscordWebhookRequestBody() : FDiscordWebhookRequestBody(FString()) {}
};
このように FJsonSerializable
を継承し JSON_SERIALIZE
などのマクロを使って構造体を定義します。
こうすることで、ToJson
関数を呼ぶだけで FString
型のJson文字列に変換することができます。
Discord Webhook URLを書いておく
別にこれはどうだっていいんですが、先程コピーしたDicordのWebhook URLをここでコードにベタ書きします。
static constexpr auto DISCORD_WEBHOOK_URL = "<WEBHOOK_URL>";
この辺はエディタの設定拡張とかでどうにかしたかったけど面倒なので諦めました
イベントリスナの実装
OnCompileFinished
の実装を書いていきます。
void FHotReloadNotificationsModule::OnCompileFinished(const FString& LogDump, ECompilationResult::Type CompilationResult, bool bShowLog) const {
const auto Body = FDiscordWebhookRequestBody(ECompilationResult::Succeeded == CompilationResult ? FString(L"[HotReloadNotifications] COMPILE SUCCEEDED") : FString(L"[HotReloadNotifications] COMPILE FAILED"));
auto Request = FHttpModule::Get().CreateRequest();
Request->SetVerb("POST");
Request->SetHeader("Content-Type", "application/json");
Request->SetURL(FString(DISCORD_WEBHOOK_URL));
Request->SetContentAsString(Body.ToJson());
Request->ProcessRequest();
}
よくあるHTTPリクエストを組み立てて送信しているというコードです。
EComppilationResult::Type
列挙型には Succeeded
以外にもいくつかの列挙値が存在しますが、ここでは Succeeded
のみの判定としています。
先程 FJsonSerializable
を継承して作成した FDiscordWebhookRequestBody
のインスタンスから、 ToJson
関数を使って文字列に変換しています。(めちゃくちゃ便利)
確認
Visual Studioからのビルドが完了した上で、UE4のコンパイルを実行します。
DiscordにちゃんとWebhookが飛んできていたらOKです。
まとめ
今回の成果物 ekuinox/UE4-HotReloadNotificationsはこちらです。
株式会社ヒストリアさんの[UE4] Slack連携してライトビルドの完了を通知する を読んだところ、コンパイル通知もやりたいなと思って実現したものです。(JsonやHTTP周りも大変助かりました)
ただ IHotReloadInterface
にたどり着くまでには地味に時間がかかっていて、GitHub上のUE4のソースを検索かけて探しました。
UE4で用意されたクラスの使用例が見たくて検索かけてんのにエンジンのクローンリポジトリばかりヒットするのクソだろ 謎クローンをやめろ
できることなら、より時間のかかるパッケージングの通知も取得したかったのですが、今回は心が折れました。知見のある方はコメントとかでご教示いただけるとめちゃくちゃ嬉しくなります...。