この記事は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で用意されたクラスの使用例が見たくて検索かけてんのにエンジンのクローンリポジトリばかりヒットするのクソだろ 謎クローンをやめろ
できることなら、より時間のかかるパッケージングの通知も取得したかったのですが、今回は心が折れました。知見のある方はコメントとかでご教示いただけるとめちゃくちゃ嬉しくなります...。


