Unreal Engine (UE) のプロジェクトは、ブループリントか C++ のみを使用して作成できますが、ほとんどのプロジェクトでは、それら 2 つを組み合わせて使用することでメリットを得られます。では、プロジェクトに最適なブループリントと C++ の組み合わせを決定するにはどうすればよいのでしょうか。本書では、そうした疑問を解消する方法についてのガイダンスを示します。
プログラミングとスクリプティングの比較
ブループリントまたは C++ を使用するタイミングを見極めるには、まずプログラミングとスクリプティングの違いを理解する必要があります。
- プログラミング:システムを定義する指示。
- スクリプティング:既存のシステムと連携して動作を定義する指示。
たとえば、加速やステアリングなどの基本機能を処理するビークル (乗り物) のシステムを定義するにはプログラミングを、車やボートなどの特定のビークル (乗り物) のタイプを定義するにはスクリプティングを使用します。
このコンテキストでは、C++ がプログラミング言語、ブループリントがスクリプティング言語となります。ただし、C++ を使用して動作を定義したり、ブループリントを使用してシステムを定義したりできるため、それは明確な違いではありません。さらに、プロジェクトでプログラミングとスクリプティングの境界が曖昧な場合もあり、2 つをどのように分けるのかはシナリオによって異なります。
ブループリントは、公開されている UE の機能と連携することによってスクリプティング言語として機能します。同じように、ブループリントにカスタム機能を公開できます。詳細については、ブループリントと C++ を組み合わせる を参照してください。
ブループリントと C++ を比較する
どのプロジェクトやチームも一意であるため、ブループリントと C++ のどちらを使用するのかを決定するにあたって「正しい選択」はありませんが、それらを使用する前にそれぞれの強みについて考えることをお勧めします。
ブループリントの強み
- スクリプティング:ブループリントは動作を簡単に定義できます。
- 迅速なイテレーション:ブループリントは、ブループリント クラスをすばやく作成、変更、コンパイル、テストできるため、プロトタイピングに最適です。
- 広範なアクセシビリティ:ブループリントのビジュアル フロー表現は、わかりやすくて使いやすく、ビジュアル志向のプログラマー、またはデザイナーやアーティストのようなプログラマー以外のユーザーが利用しやすいものとなっています。
- 見つけやすい:ブループリントを使用すれば、API やアセットの参照を簡単に見つけて含めることができます。
- 安全なメモリ モデル:ブループリントは安全なメモリ モデルでクラッシュを回避するように設計されています。
C++ の強み
- プログラミング:C++ は新しいシステムを簡単にビルドできます。
- 高いランタイム パフォーマンス:C++ はパフォーマンスに優れていますが、そのレベルはコンテキストによって異なります。詳細については、後述の「パフォーマンスに関する懸念事項」セクションを参照してください。
- 広範なアクセス:C++ は、下位レベルの UE の機能にアクセスできます。
- 広範な拡張性:C++ を使用すれば、外部のシステムやライブラリを作成してそれらと連携できます。
- 優れた制御:C++ は、システム、リソース、複雑なアルゴリズムに対する低水準言語レベルの制御を付与します。
- スムーズなコラボレーション:C++ はテキストとして格納されるため、差分確認、マージ、プロジェクト間での共有が容易です。ただし、ブループリントでは Unreal Diff ツール を使用できます。
- 優れたスケーラビリティ:大きい C++ ファイルは、大きいブループリント グラフより変更が容易です。
- 優れたデバッグ:C++ には、ブループリント デバッガ より強力なデバッグ ツールがあります。
パフォーマンスに関する懸念事項
次のような理由から、C++ は基本的にブループリントよりパフォーマンスに優れています。
- C++ は、CPU で直接実行されるマシン コードにコンパイルする。
- ブループリントは、仮想マシンで実行されるバイトコードにコンパイルする。
そのため、ブループリントではスクリプト実行のオーバーヘッドが増加します。ただし、ブループリントと C++ のパフォーマンスの違いは通常わずかしかなく、コンテキストによって異なります。以下に、最も影響が大きいと思われるコンテキストの例を示します。
- 中核となる下位レベルのインフラストラクチャ。
- I/O または処理リソースを多用する緊密なループ。
- 大規模データ セットを処理するシステム。
- 多くのインスタンスがあるティックに依存するクラス。
- マルチスレッドのメリットを得られるシナリオ (ブループリントではサポートされないため)。
パフォーマンスを向上させるには、ティックではなくタイマーかデリゲートを使用してブループリントでの作業のスケジュールを設定します。
ブループリントを使用しており、パフォーマンスの問題が発生している場合は、Unreal Insights でプロジェクトをプロファイリングし、最も重大なボトルネックを最適化してから ブループリントを C++ に変換する ことを検討します。
ブループリントと C++ を組み合わせる
ブループリントと C++ を組み合わせる最善のアプローチとしては、基盤として C++ を使用し、その上にブループリント クラスをビルドします。実際のところ、このようにすると C++ が公開されてブループリントから使用できるようになります。
C++ は、次のような方法でブループリントに公開できます。
- C++ クラスを拡張するブループリント クラスを作成し、
UPROPERTY(BlueprintReadWrite)
やUFUNCTION(BlueprintCallable)
のような メタデータ指定子 を使用して特定の要素を公開します。 UBlueprintFunctionLibrary
を拡張する C++ クラスを作成してクラスの静的関数を公開します。
あまり一般的ではありませんが、次のような方法でブループリントを C++ に公開することも可能です。
UFUNCTION(BlueprintImplementableEvent)
指定子を使用して、ブループリントで実装する必要がある純粋な仮想関数を定義します。UFUNCTION(BlueprintNativeEvent)
指定子を使用して、ブループリントで任意でオーバーライドできる仮想関数を定義します。- ユーザー インターフェースを作成するときに、
UPROPERTY(meta=(BindWidget))
を使用してブループリントで作成された UserWidget にアクセスできます。
これらの方法の詳細については、次のページを参照してください。
- C++ とブループリント:ブループリントで拡張可能な C++ クラスの作成に関する詳細例。
- C++ をブループリントに公開する:ブループリントフレンドリーな API の記述に関するヒントとコツ。
- ゲームプレイ要素をブループリントに公開する:ブループリントへのゲームプレイ要素の公開に関するゲームプレイ プログラマー向けのテクニカル ガイド。
- ブループリント関数ライブラリ:
UBlueprintFunctionLibrary
の使用方法を解説。 - Lyra のサンプル ゲーム:前述の各方法の例が含まれる Lyra プロジェクトについて解説。
ブループリントを C++ に変換する
ブループリントを C++ に変換する場合は、まず ブループリント ヘッダ ビュー を使用してブループリント クラスまたは構造体用の C++ ヘッダ ファイルを生成します。生成された .h
ファイルには、ブループリントのすべての変数と関数の宣言が含まれますが、関数実装を一致する .cpp
ファイルに手動で変換する必要があります。
ブループリントを C++ に変換すると、場合によっては新しい C++ クラスを使用するために参照を更新する必要があります。これによって多数の更新が必要になる場合は、Core Redirect を使用してそれらの参照を自動的に再マッピングすることを検討してください。