Let's Enjoy Unreal Engine

Unreal Engineを使って遊んでみましょう

UE4 エンジン改造せずにエンジンに手を入れる方法

この記事はUnreal Engine 4 Advent Calender 2018の1日目の記事です。

qiita.com

1日目で恐縮ですが、この記事は完全にダークサイドUE4な内容となっておりますので、UE4初心者が読むことを全く考慮しておりません。読む際には十分承知の上で読み進めてください。

UE4ではエンジンのソースコードGitHub上に公開されているため、自分でリポジトリーからソースコードを拾ってきて、それをビルドすることでエンジンをいくらでもカスタム可能な事がウリのひとつとなっています。

が、世の中にはエンジンを改造するにはちょっと荷が重いプロジェクトが大半で、エンジン改造されたリポジトリーを共有するというのはかなりインフラが整ったゲーム会社でなくては厳しいという現実があります。

実際UE4のプロジェクトでもゲーム、VR、映像と関わってきましたが、エンジンを改造せずに、uprojectが入っているフォルダー以下を共有するという現場もそこそこありました。大規模なゲーム開発をしている現場からすれば「そんなのエンジンに少し手を入れればイーじゃん」くらいの感覚かもしれません。


しかし!
なぜかエンジンを改造したい!!
バグをどうしてもなんとかしなくてはならない!!!


といった、状況がそこそこ大量にあります。

もし、エンジンを改造せずにエンジンに手を入れる方法があるとすれば難易度別の選択肢としては以下のようなものがあります。


難易度 Lv1 : エンジン側のクラスを継承し、関数をオーバーライドする
難易度 Lv2 : エンジンのソースコードをゲームモジュールにコピーして利用する
難易度 Lv3 : エンジンモジュールを丸ごと上書きし、ゲームモジュール側で乗っ取る


Lv1 は特に改造でもなんでもないですが、エンジン側のクラスの関数がオーバーライドできるのならこれだけでも出来る事はそれなりにあります。

Lv2 はそこそこコアなUE4使いであればやったことがある人もいると思います。基本的にはこの内容を期待していた人が多いのではないかと思います。

Lv3 は未知の領域です。ダークサイドです!今回はこれについてを取り上げます!そもそも乗っ取るとはどういうことなのか…?

それでは早速詳しい話へといきましょう。
今回の検証は全てEpic Games LauncherからDLした、UE4.21.0にて検証しております。

尚、今回の結果を実際に試してみて問題が発生したとしても、いかなる責任も負いかねますのでご了承ください。

モジュールとは

UE4はエンジンからゲームコンテンツまでを含めて、全てのプログラムはモジュールという単位でシステムがビルドされています。

f:id:alwei:20181120220326p:plain

UE4システム簡易概略図です。

モジュールは最終的にDLLとしてビルドされたものをUnreal Build Toolで依存関係を確認し、必要に応じてリンク作業が行われるようになっています。ゲーム側やプラグインは基本的にエンジンのモジュールに依存しているため、エンジンのモジュールなしで動作することはできません。

UE4はDLLによってリンクされているため、必要に応じてホットリロードによりモジュールを動的にコンパイルし、差し替えられるような作りになっています。

このような作りになっているために、モジュールを必要に応じて差し替えるような事が可能という事では…?

エンジンモジュールを差し替えてみる

というわけで、早速試していきます。今回は4.21のSourceフォルダー内のEditorに入っている、"Blutility"を検証材料に使ってみました。

f:id:alwei:20181120221948p:plain

これを今回用に作成した"EingineCustom"というC++のプロジェクト内の"Source"フォルダー内に丸ごとコピーします。

f:id:alwei:20181120222251p:plain

当然なんですが、エンジンからコピーしてきたソースコードは読取専用になっており、後でソースコードを書き換えられるように、フォルダーのプロパティから読取専用属性を外すようにしておきます。

ビルドするモジュールを指定する、"EngineCustom.Target.cs"を書き換えて、"Blutility"をゲーム内モジュールに含めるようにします。

f:id:alwei:20181120223004p:plain

あとはuprojectファイルを右クリックして、Visual Studio用のプロジェクトファイル一式を作り直します。これでモジュールのソースコードが登録されます。

f:id:alwei:20181120223118p:plain

さぁこれでビルドしてみましょう!!



f:id:alwei:20181120223442p:plain

見事にビルドエラーが出ました…

重要な部分だけ切り取ると

Engine module should not depend on game module

この英文を翻訳すると、

"エンジンモジュールはゲームモジュールに依存してはならない"


/(^o^)\ ダヨネー


普通の人はここで諦めてしまうはずです。私はなぜか諦められませんでした。

エラーを強制的に書き換える

今回のエラーはUnreal Build Tool上から発生したものです。

ここで私は思いました。


( ゚д゚)ハッ (Unreal Build Toolを書き換えればいいんじゃね?)


Unreal Build ToolはランチャーからDLしてきたUE4では既にビルド済みバイナリーが入っていますが、GitHubからDLしてきたものであればソースコードもついてくるので、自分でビルド可能です。

ここで、DLしてきたUE4GitHubリポジトリーを4.21ブランチに切り替えを行い、UBTソースコード書き換えを行います。いよいよダークサイドっぽくなってきました。

エンジン用のVisual Studioプロジェクトを開き、上記エラーのあるソースコードを検索します。

f:id:alwei:20181120230113p:plain

Unreal Build ToolのC#プロジェクトから、該当のソースコードは"UEBuildTarget.cs"というファイルの2013行目辺りにあることがわかりました。
そのソースコードコメントアウトし、警告文を流すだけに修正します!!

そしてUBTだけをビルドすると、バイナリーが"Engine/Binaries/DotNET/UnrealBuildTool.exe"に出力されているはずです。

ここで出力された"UnrealBuildTool.exe"をランチャーから落してきたUE4のエンジン側の同じ位置にコピーします。

f:id:alwei:20181120231344p:plain

念の為、元ファイルのバックアップも残しておきます。

さてこれでビルドするとどうなるか…


f:id:alwei:20181120231827p:plain

おお…エラーは出たけど、先程の"エンジンモジュールはゲームモジュールに依存してはならない"という部分が見事に警告扱いになりました!

残りのエラーはインクルードの問題のようにも見えます。警告の中にプリコンパイル済みヘッダーの使用を指定しろというようなものがありますので、"Blutility.Build.cs"に下記のコードを加えました。

f:id:alwei:20181120232356p:plain

"PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;"という一行を加えることで、このモジュールに共有プリコンパイル済みヘッダーを利用しますという指定を行うことが可能です。
おそらくエンジン側ではこの指定が共通でかかるような仕組みが入っているのだと思います。

これでビルドを行うと…


f:id:alwei:20181120232717p:plain


ビルド完了シタ━━━━(゚∀゚)━━━━ッ!!


というわけで無事エンジンモジュールのビルドが完了しました。これで晴れてエンジンの一部をゲームモジュールで乗っ取ることが可能になります。

ただし、ここに至るまで沢山のトライ アンド エラーがあり、何度かエンジンモジュールのバイナリー(DLL)が壊れたり、消失するような事がありました。

このようになった場合には、慌てずにEpic Games Launcherからエンジンの"Verify(修復)"を行うようにしてください。基本的にこれさえ行えばいくらぶっ壊してもDL時点の状態へと元通りになります。※書き換えたUBTなども戻る

f:id:alwei:20181120233212p:plain

実際に起動してカスタムしてみる

これでエンジンモジュールが上書き出来ているはずなのですが、実際に確認してみなくてはわかりません。

今回はBlutilityの"BlutilityModule.cpp"内のソースコードを一部書き換えてみて、実際に上書き出来ているのか確かめてみました。

f:id:alwei:20181120233958p:plain

この状態でビルドし、UE4エディターを起動します。

f:id:alwei:20181120233649p:plain

Blutilityシェルフのウィンドウ上のタブの文字列が変わっていることが確認できます!無事上書き出来ていることが確認できました!!

これでBlutilityモジュールをゲームモジュール内から弄る事が可能となりました!

プラグイン化も可能

このテクニックを応用し、エンジンモジュールをプラグイン化する事も可能です。通常のC++プラグインを作るのと同様の手順でプロジェクトの"Plugins"フォルダーに関連するファイルを全て入れておきます。
upluginファイルやResourcesフォルダーはBlankプラグインなどを作成し、そこの内容をそのままコピーして持ってきます。

f:id:alwei:20181120234532p:plain

あとはこのままVisual Studioプロジェクトファイル一式を生成し、ビルドして起動します。

f:id:alwei:20181120234909p:plain

プラグインニ (n‘∀‘)η ナッタワー


プラグインにする事で、配布も容易になります。またC++プロジェクトである必要もなくなり、ブループリントプロジェクトでも運用可能になります!
ブループリントプロジェクトでもエンジンに手を入れることが可能と考えると、色々と夢が広がりますね!

最後に

ここまでエンジン改造を行わなくてもエンジンの中身に手を加える方法についてを色々と解説してきました。

ただし、この方法は完全にバッドノウハウです。本来依存関係を持っているモジュールを無理矢理切り離してビルドしている以上、何かしら問題が発生する可能性があります。
小さい修正であれば恐らく大丈夫ですが、大きな修正は他のモジュールに大きく影響を与え、最悪エンジンがクラッシュします。

Unreal Build Toolのエラーと警告を無視しているので、本来やってはいけない事であるのは間違いありません。用法・要領を守って、計画的に正しいエンジンカスタマイズを行ってください!


明日は荻野雄季さんによる「前々から自分が言っていた宿題を片付ける。」という内容だそうです。どんな宿題なのか楽しみにしています。