【UE5】エンジンやプラグインのシェーダーをホットリロードしてみた – Unreal Engine 5.6

Unreal Engine

水ノ茉の宣伝

準備中...
ゲームを作る予定なの
水ノ茉こおり

始まり

コンテンツのひとつであるCoffeeLiveではすべて専用のシェーダーを使用して描画しています。

Coffee Live
「Coffee Live」の記事一覧です。

GBufferに書き込むためのシェーダーならToonBasePassVertex/PixelShader.usfだったり、ライティングならDeferredToonLightVertex/PixelShaders.usfだったりです。

独自のシェーダーは表現と最適化で理論値を叩き出せる反面、開発効率が悪いという欠点を抱えています。独自で実装したシェーダーの変更を反映するには、“基本的には”UnrealEngineを再起動する必要があるためです。いくつか例外はありますが、シェーダーのコンパイルが起動時にしか行われないのが理由です。これはエンジンのような低層に限らずプラグインやプロジェクトのような高層でも同様です。

そう、基本的には、ね。

エンジンまわりを作業場所としているエンジニアや、パッケージビルドなどのインフラ整備をしている方ならご存知でしょうが、実はシェーダーのホットリロードの手段が提供されています。手段は提供されていますが、UEがランタイムに動作している最中に使うことはあまり想定されていないため、愚直に使うとエラー落ちします。

前述の通りCoffeeLiveでは独自のシェーダーしか使っていないので幾らシェーダー開発に慣れていて試行回数を少なく抑えられるといっても限度がありました。あとライティングシェーダーは大量のバリエーションを試したいという欲望もあり、それと相性が悪かったです。要約すると再起動フローを踏むのがクソほど怠かったのです。

なので、独自のシェーダーのホットリロードをワンポチで出来るようについでに整備しました。

導入手順

エンジン改造を1か所とプラグインの導入が必要です。

GlobalShaderを実装する方はエンジニアしか居ないでしょうし、仮にアーティストでそれを出来るレベルなら技術的に懸念はないでしょうから、諦めてエンジンを弄ってください。エンジン改造とか仰々しい名称が付いていますが、所詮は書き換えているコードのディレクトリが違うってだけですからね。

Engine/Source/Runtime/Renderer/Private/SceneRendering.cpp

ShowFlag.Rendering 0で描画機能を封じたいので以下のように書き換えてください。

//// ReinCarnation @kobayashi-arata 2025/06/20 ////
#if WITH_EDITOR
	if (Scene && ViewFamilies[0]->EngineShowFlags.Rendering)
#else
	if (Scene)
#endif
//// ReinCarnation @kobayashi-arata 2025/06/20 ////

githubで実装を見る

本来であればShowFlag.Rendering 0を叩くだけで描画機能が封じられるべきなのですが、バージョン5.6.1までは2つの不具合があり、改造が必須です。

1つは配列外アクセスを引き起こします。これは5.7で修正されます。というかbFirstRendererbLastRendererは未使用変数なのでこんなゴミを残すなとコード規約に文句を言いたい。

仮に上記の不具合修正を5.7からバックポートしたとしても、もうひとつ不具合が残っています。

ShowFlag.Rendering 0を指定した状態でマウスカーソルをビューポート内に移動させてクリックなどをしてフォーカスを移すとRenderHitProxiesのセットアップが失敗します。ShowFlag.HitProxies 0を併用しても回避不可です。根本的な修正方法を探るのはEpicや有志の方に任せるとします。

ShaderHotReloadプラグインの導入

クローンをするか、Releasesからダウンロードするか、好きな方を選んでください。

GitHub - kafues511/ShaderHotReload
Contribute to kafues511/ShaderHotReload development by creating an account on GitHub.
Release 1.0 ?? kafues511/ShaderHotReload
Unreal Engine 5.6.1ShaderHotReload.zip

プロジェクトのプラグインディレクトリに配置してください。配置した後に念のためGenerateProjectFiles.batを叩いてソリューションを更新した方がいいかもです。

導入が成功していればエディタの上部にボタンが追加されているはずです。

表示されない場合は、プラグインが謎に無効化されていないか確認するといいです。

使用方法

シェーダーを“正しく”書き換えた後に先ほどの追加されたボタンを押すだけです。コンパイル中は不必要な操作は基本避けてください。描画機能の封じ方がかなり適当なので、余計なことをするとクラッシュする可能性が十分にあります。

シェーダーコードの編集を間違えた場合は、コンパイルエラーでクラッシュします。これは失敗時にデフォルトシェーダーをアタッチする仕組みが存在しないためです。現状は気を付けて書いてくださいね。

上記の例だとセミコロンが付与されていなくてコンパイルエラーが発生です。

FAQ

  • SlateShaderのホットリロードは非対応
    • UnrealEditorがSlateに依存しているのでこれを封じるのが面倒だった。
  • シェーダーコードを間違えたらクラッシュした
    • 仕様です。
  • クラッシュした
    • そういうこともある。本来はエンジン再起動必須だから落ちたところでゼロに戻るだけ。
  • ‘ShaderHotReload’ is Incompatible
    The ‘ShaderHotReload’ plugin was designed for build 5.6.0 Attempt to load it anyway?
    • とりあえずYesをクリックして通過することを祈りましょう。

保守メモ

プラグインをビルド

F:\CoffeeLive\Engine\Build\BatchFiles\RunUAT.bat BuildPlugin -Plugin=F:\CoffeeLive\CoffeeLiveGame\Plugins\ShaderHotReload\ShaderHotReload.uplugin -Package=F:\CoffeeLive\CoffeeLiveGame\Pak\ShaderHotReload -HostPlatforms=Win64 -TargetPlatforms=Win64

Binariesからpdbを削除

SourceからPrivatePublicを削除

ShaderHotReload.Build.csbUsePrecompiledを追記

bUsePrecompiled = true;

更新メモ

  • v1.0.1
    • ホットリロードを試行したら描画機能を止めてから処理を進行するように変更
      • 負荷が高いプロジェクトで使用した際に、ホットリロードが進行可能な状態をキャッチしてから描画機能を止めようとしても、上手いこと同期取れずに競合することがあったため。
  • v1.0.0
    • 初版

おわり!!!

前々からホットリロード対応したいなと思いつつ、シェーダーコードなんてポポンと書けるので永遠と後回しにし続けて1年ぐらいが経過しました。

ちょうどいい機会&気分だったので未来の私のために整備してあげたのです。

あとわたし、プラグインのアイコン画像をそのうち変えてね。めっちゃ適当なの。

体験版の履修は別にいいか

ライムライト・レモネードジャム|ゆずソフト
ゆずソフト最新作ライムライト・レモネードジャムのPC版公式サイトです。

まぁ、別に、ええか。

基本的には別にエロゲプレイしたいんですよ。

ただね、コード書くのも楽しいのですよ。

最近はGPUクロスシミュにハマってます。

揺れがエッチすぎてモチベの相乗効果がすごいの。

最近バージョンアップの頻度がヤバい

これを書いているのが9月初旬です。

5.6アプデから半年も経ってないですよね。