BLOGブログ

2019.07.03UE4UE/ C++

[UE4] データテーブルの内容を使って変数の中身を一覧から選択させる方法

執筆バージョン: Unreal Engine 4.22

皆さんこんにちは。今回は便利な機能の実装方法をご紹介したいと思います。ゲーム開発においてイテレーションの最適化やバグを未然に防ぐ実装は常に課題になっているかと思います。そこで今回ご紹介する機能は、プログラマが事前に用意しておく事でレベルデザイナーの作業が効率化し、バグが発生しにくくなるというものです。

はじめに

さて、みなさんはUE4のデータテーブルは使っていますか?事前に静的なデータを用意しておき、ゲーム内でそれを参照することはよくあることだと思います。そこで有効になってくるのがデータテーブルです。特にUE4ではcsvファイルから簡単に指定した構造体でのデータテーブルアセットを用意することが可能です。詳細についてはこちらの記事を参照下さい。

さて、今回はキャラクターの名前とステータスの一覧をこんな感じで用意しました。ちなみに構造体はブループリントで用意しましたが、後々の取り回しを考えるとC++側で定義した方がよいでしょう。

次にこのデータテーブルを利用して、キャラクター名からキャラクターのステータスを取得する関数を作成します。

 

当然呼び出し側はこんな感じになるはずです。引数のCharacterNameはName型になりますし、ノードを使う側はその文字列を手で入力することになります。

ですがこのCharacterNameはデータテーブルの中から探してくるものであり、本来なら以下のようになって欲しいはずです。  

ノードを利用する側はデータテーブルの一覧から選択したいわけですし、レベルに配置したアクターのプロパティを編集する場合も同じように一覧から選択する方が効率よく、また手入力による間違いも発生しなくなるはずです。

 

つまり顧客が本当に欲しかったものはName型ではなく、データテーブルのRowデータが列挙されるようなEnum型に近い型になるはずです。

実はこのノードのピンをプルダウンメニューから選択する方法、過去に弊社ブログで紹介した機能になります。今回はこの機能を使いつつ、更に詳細パネルの方もついで実装してしまおうというわけです。 それでは、どうやればこれらが実装できるかを解説していきたいと思います。ちなみにこれらの実装には事前に以下の内容が必要になってくるため、それぞれ過去のブログ内容をご参照下さい。 configに項目を追加 → [UE4]「エディタの環境設定」や「プロジェクト設定」に項目を追加する エディタ用にモジュールを追加 → [UE4] モジュールについて

実装手順

1.C++側でデータテーブルが参照できるようにiniファイルにアセット参照を追加

まず準備としてC++側でアセットデータを簡単に参照できるように、configファイルにデータテーブルのアセット参照を追加します。 新規作成するTestSettings.hの実装です。cppは特に何も書きません。

既存の<ProjectName>.ppの内容です。今回はプロジェクト名がTestなので、Test.cppになります。

プロジェクト設定に項目が追加されたら該当のデータテーブルアセットを設定します。

 

2.エディタ用モジュール作成

自作用のピンや詳細パネル表示用の処理をランタイムと分けるためにエディタ用にモジュールを作成します。その際、エディタ側で使用する別モジュールを忘れずに追加しておきましょう。 新規作成したTestEd.Build.csは以下のようになります。

 

3.実際に使用する型の追加

以上で準備が完了したら、次は今まで使用していたName型に変わる新しい型を定義します。ここではキャラクターステータス用のデータテーブルなので、それが分かるような構造体名にします。ちなみに同じように別のデータテーブルでこの機能を作る場合、中身は全く同じで名前のみを変更した別の構造体を定義する事になります。この構造体はランタイム時も使用することになるので、当然ゲームモジュール側に追加して下さい。 新規作成したCustomPinStruct.hの中身です。cpp側は特に何も書きません。

 

4.自作ピンの作成

まずはノードのピンの処理を実装します。この処理に関してはエディタのみでしか使用しないためエディタモジュール側に追加することにご注意下さい。また、後述する理由により、実際にデータテーブルを参照して文字列を列挙する処理は別クラスに分けているため、この時点ではまだビルドは通りません。ここでも別途データテーブルを増やしたい場合は、SCustomGraphPinBaseを基底クラスとした別クラスを追加し、SetDisplayStrings関数の中で呼び出す関数を変更することになります。また、FCustomGraphPinFactoryクラス内のCreatePin関数で、「3」で追加定義した構造体と先程追加したクラスを紐付ける処理を追加します。 新規作成したCustomGraphPin.hの中身です。

新規作成したCustomGraphPin.cppの中身です。

5.データテーブルから文字列を列挙する処理の追加

今回の肝となる部分です。プロジェクト設定から指定したデータテーブルアセットを参照し、Rowデータを渡す処理を実装します。この処理は自作ピンの他、詳細パネルの表示部分でも使用するため、別クラスに分けるようにします。もちろん、別途データテーブルを増やしたい場合は、ここに関数を追加していくことになります。 新規作成したCustomDisplayList.hの中身です。

新規作成したCustomDisplayList.cppの中身です。

6.詳細パネルの表示処理を追加

続いて詳細パネル側の表示処理を追加します。こちらも自作ピン同様エディタモジュール側の処理となります。そして自作ピンと同様、データテーブルを追加する場合はこちらもICustomDetailBaseを基底クラスとしてた別クラスを追加し、SetDisplayStrings関数の中身を変更しましょう。 新規作成したCustomDetail.hの中身です。

新規作成したCustomDetail.cppの中身です。

7.エディタモジュールの編集

最後に、モジュール登録時にこれらのピンや詳細パネルが動くように登録します。自作ピンに関してはファクトリークラスを1つだけ登録すれば完了ですが、詳細パネルの方はデータテーブルを増やすたびにこちらに処理を追加して行くことにご注意下さい。 TestEd.cppの中身です。

 

使い方

以上で、実装方法は完了しました。続いて実際の使用方法ですが、まず引数がName型だったものを今回新しく用意した構造体に変更します。

このままでは構造体なので中身をバラしてKeyを取り出します。この中身がデータテーブルから取得してきた文字列になります。

もちろんただの構造体なので右クリックの「Split Struct Pin」で簡潔にすることも可能です。

   

最後に

さて、これでわざわざ文字列を手入力することなく、データテーブルのデータを簡単に取得できるようになりました。ですがこの機能には少し問題があります。それはデータテーブルの種類が増えた時、これらの追加対応がちょっと面倒な所です。もう少し自動化できるとよいのですが、その方法は只今模索中です。なにか思いつけば後日ご紹介したいと思います。