関連ブログ
- [UE4][UE5]開発環境の容量を少しでも減らす 2024.08.14UE
- [UE5] PushModel型のReplicationを使い、ネットワーク最適化を図る 2024.05.29UE
- [UE5]マテリアルでメッシュをスケールする方法 2024.01.17UE
CATEGORY
2015.06.17UE4UE/ C++
改訂バージョン: Unreal Engine 4.21 |
今回は、UE4のC++コードをビルドする際に知っておきたい、モジュールの概念と実装方法について説明します。
完全にプログラマ向けですし、簡単なゲームを作るだけであれば知らなくても動かせる内容ではありますが、UE4をしっかりと使いこなすためには、把握しておいた方がよい内容です。
UE4のC++コードは、「モジュール」と呼ばれる単位で、「UnrealBuildTool」を通してビルドされます。
この時「モジュール」毎に、Windowsではdllファイル、Macではdylibファイルが作られます。
これは、エンジン内部のコードでも、プラグインでも、ゲームプロジェクトでも共通です。
ゲームプロジェクトもプラグインも、それぞれが複数のモジュールを含むことが出来ます。
また、ビルド構成によってロードするモジュールを切り替えることが出来るため、エディタ専用のモジュールや開発用ビルド専用のモジュールを作ることで、#ifdefよりも大きくまとまった単位で、機能を切り分けることが出来ます。
メインメニューの [Window] -> [Developer Tools] -> [Modules] から、エンジン内部も含めた、全てのモジュールの一覧を確認することが出来ます。
通常、プロジェクトにC++コードを追加すると、下記のようなフォルダ構成が作成されます。
Source |- MyProject.Target.cs |- MyProjectEditor.Target.cs |- MyProject |- MyProject.Build.cs |- MyProject.cpp |- MyProject.h |- ... |
最初に登録されるモジュールの名前は、プロジェクト名と同一です。なので、上記のフォルダ構成は、実は下記のような意味になっています。
Source |- [プロジェクト名].Target.cs |- [プロジェクト名]Editor.Target.cs |- [モジュール名] |- [モジュール名].Build.cs |- [モジュール名].cpp |- [モジュール名].h |- ... |
このとき、[モジュール名]フォルダ以下が、1つのモジュールとしてビルドされる範囲となります。
また、Sourceフォルダの追加だけでなく、.uprojectファイル(プラグインの場合は .upluginファイル)に下記のような記述が追加されます。
1 2 3 4 5 6 7 |
"Modules": [ { "Name": "MyProject", "Type": "Runtime", "LoadingPhase": "Default" } ] |
これが、このプロジェクトに含まれるモジュールを列挙している記述になります。
標準のエンジン機能のみでゲームを開発する場合には、1つのゲームモジュールがあれば十分ですが、 エディタ拡張を行う場合等には複数のモジュールに分けておくと便利な場合があります。
モジュールの”Type”には、いくつかの種類がありますが、主に使用するのは”Runtime”と”Editor”です。
(詳しくは公式ドキュメントを参照して下さい)
“Runtime”は、ゲームの実行時に必要になるモジュールで、常にロードされます。
“Editor”は、ゲームの実行時には必要ない、エディタ上での動作に必要なモジュールです。 パッケージされたゲームや、Shippingビルド時にはビルドされず、当然ロードもされません。
以前の記事で、プラグインによるエディタ拡張の方法をご紹介しましたが、このような内容のコードは本来”Editor”モジュールに実装すべきです。
また、独自のアセットを実装する方法でご紹介した内容では、本来はアセットクラス自体は”Runtime”モジュールに、FactoryやAssetTypeActionsといったエディタ用の機能は”Editor”モジュールに実装すべきです。
SpriteStudioプラグインでも、そのようにモジュールの分割を行っています。
では、実際にゲームプロジェクトにエディタモジュールを追加する手順をご紹介します。
今回は、”MyProjectEd”という名前のエディタ専用モジュールを追加します。
まず、先ほどの .uprojectファイルを下記のように修正します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
{ "FileVersion": 3, "EngineAssociation": "4.21", "Category": "", "Description": "", "Modules": [ { "Name": "MyProject", "Type": "Runtime", "LoadingPhase": "Default" }, { "Name": "MyProjectEd", "Type": "Editor", "LoadingPhase": "Default" } ] } |
続いて、モジュール用のソースコードを追加します。
最低限必要なコードは、下記の通りです。
Source |- MyProjectEd |- MyProjectEd.Build.cs |- MyProjectEd.cpp |- MyProjectEd.h |
ファイルの内容は、最初の「MyProject」モジュールからコピーして、モジュール名の部分だけ置換すればOKです。
続いて、Source / MyProjectEditor.Target.cs の SetupBinaries関数内ExtraModuleNamesを、以下のように修正します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// Fill out your copyright notice in the Description page of Project Settings. using UnrealBuildTool; using System.Collections.Generic; public class MyProjectEditorTarget : TargetRules { public MyProjectEditorTarget(TargetInfo Target) : base(Target) { Type = TargetType.Editor; ExtraModuleNames.AddRange( new string[] { "MyProject", "MyProjectEd" } ); } } |
ココに記述するか、記述されたモジュールから間接的に参照されるかしないと、コードだけを追加したモジュールはビルドの対象になりませんので注意して下さい。
[プロジェクト名].Target.cs がランタイム用、[プロジェクト名]Editor.Target.cs がエディタ起動時用です。
これで、エディタ用モジュールが実装出来ました。
最低限のエディタ用モジュールを実装したサンプルプロジェクトを添付しておきますので、参考にして下さい。
次に、実装したモジュールの機能を外部から使用する方法です。
おそらく、MyGameEdモジュールからMyGameモジュールの機能を使用したいことがあるでしょう。
外部モジュールへの参照は、.Build.csファイルの PublicDependencyModuleNames にモジュール名を記述することで追加出来ます。
しかし、そもそも参照先のモジュールが機能を外部公開していなければ、モジュール外から関数呼び出しやクラスの参照を行うことが出来ません。
外部公開するクラスや関数の宣言の前に
[モジュール名]_API |
というマクロを追加することで、その機能をモジュール外に公開することが出来ます。
例えば “MyProject”モジュールであれば”MYPROJECT_API”、”UnrealEd”モジュールであれば”UNREALED_API”、”Paper2D”モジュールであれば”PAPER2D_API”といった形です。
エンジン本体や標準プラグインのコードをみると、あちこちでこのマクロを見つけることが出来ると思います。
どこからも参照される予定のないモジュールであれば、この宣言は不要ですが、C++からのアクセスを考慮したプラグインや、エディタモジュールを追加する予定のゲームのランタイムモジュールなどでは、適切に外部公開を行う必要があります。
モジュールの概念は、UE4の設定を知るうえで非常に重要です。
UE4のC++プロジェクトを適切に設計/運用するためにも、しっかりと押さえておきましょう。