最近の制作で、Unityアセットの「Game Data Editor」を使いました。
なかなか便利だったので使い方などを備忘録として書いておこうと思います。
そもそもどういうアセットなのか
様々な機能がありますが、ざっくり言うと外部データ管理アセットです。
ゲーム制作において、プログラム外のテキストファイルなどにデータを置きたい事は良くあると思います。
(アイテムの情報やクイズの問題など)
このアセットを使うと、
- エディタ画面上でデータを作成できる(JSON形式で保存される)
- ExcelやGoogle Spreadsheetで作成したデータをインポートできる
(ただし特定の書式に従って記入する必要がある) - 作成したデータを暗号化できる
- Web上に保存されたデータを読み込んでゲーム内で使用できる(はず)
- 他にもいろいろ(Playmakerサポートなど)
上記のような事を比較的簡単に実現できます。
使い方
ぶっちゃけ公式サイトの記事を見たほうが分かりやすいと思いますので、
英語に抵抗無い方はそちらを見て下さい。
今回は、Excelなどを使わず、Game Data Editorが持つビジュアルエディタ上で
データを作成する方法を説明したいと思います。
全体的な流れとしては、下記のような流れになります。
- ゲームデータの枠組み(Schema)を定義する
- ゲームデータを作成する
- ゲームデータをクラス化する(データクラスを生成する)
- スクリプト上でデータを呼び出す
1~3をやることで、4ができるようになる感じです。
各ゲームデータは2を行うことでクラスとしてスクリプト上で扱うことが出来るようになります。
実際に自分が作っていたクイズゲームの問題データ作成を例に、それぞれの工程を説明します。
1.ゲームデータの枠組み(Schema)を定義する
作成したいゲームデータにどんな情報が含まれるかを定義します。
このアセット上ではここで作る情報をスキーマ(Schema)と言っているのですがその通りで、
作成したいデータの枠組み(設計図)を作るようなイメージです。
私が作るのはクイズゲームなのですが、画像を表示して、それが例えば犬なのか、
猫なのかを二択で当てる、といった二択クイズなので、下記のような情報が必要になります。
- 画像のURL(例:犬の画像)
- クイズの説明文
- 問題文1(例:犬)
- 問題文2(例:猫)
(どちらが正解なのか、といった情報が必要な気もしますが、ここでは問題文1が必ず正解になるようにデータを作成することで、そのような情報は持たないことにしました。)
実際の作成手順は下記のとおりです。
Window -> Game Data Editor -> Define Data を選択し、ゲームデータ定義画面を開きます。
Schema Name に定義するデータの名前(例:Quiz)を入力し、Create New Schemaボタンを押す
Add a new field から、データの①タイプ(型)、②フィールド名を入力し、③Add Fieldボタンを押す
※Custom Field TypeというのはGame Data Editor上で定義したクラスをデータに含めたい場合使用します。(QuizデータにGenreデータを含める場合など)
配列などを使いたい場合は、 Is List にチェックを入れることで配列を作成できます。
ここでは、クイズの問題文を配列にした方が都合が良さそうなので、配列にしました。
完成図。Save Neededボタンを押すことで、保存できます。忘れずに押しましょう。
これでデータの定義が終わりました。
2.ゲームデータを作成する
手順1で定義したゲームデータの枠組みに従って、実際のゲームデータを作成します。
今回の例ではクイズの問題内容を登録します。
Window -> Game Data Editor -> Create Data を選択します。
Create New Item から、①登録するSchemaを選択し、②Item Nameに識別する際の名前を入力、③Create New Item ボタンを押します。
手順1で作成したSchemaの内容でフィールドが生成されるので、Valueに登録したいデータを入力します。
ひと通り入力した後、Save Needed を押すことで、所定の位置(Loadボタンの横に書いてあるパス)のJSONファイルにデータが登録されます。
3.ゲームデータをクラス化する(データクラスを生成する)
手順1で定義したゲームデータの枠組み(Schema)をScript上で使えるようにクラス化します。
Window -> Game Data Editor -> Generate Custom Extensions を選択します。
これだけで自動的にゲームデータ定義(Schema)をクラス化してくれます。
エラーがある場合、Consoleに表示されます。(画面からの作成ならエラーは出ないと思いますが)
4.スクリプト上でデータを呼び出す
手順1~3で作成したデータをスクリプト上で使う方法を説明します。
下準備
まずデータを使いたいスクリプトでGame Data Editor のnamespace(名前空間) の使用を宣言します。
using GameDataEditor; // 公式サイトのリファレンスはtypoしてるからコピペに注意だ!!
次に、GameDataEditorをInitializeします。
void Awake() { GDEDataManager.Init("gde_data"); }
ここで指定している名前はゲームデータが保存されているJSONファイルの名前です。デフォルトは”gde_data”です。(Preferencesで変更できます)
データの呼び出し(一個だけ呼び出す場合)
そしてデータを呼び出します。データを呼び出す場合はキーを使用し、対応するデータを呼び出します。
(いわゆるハッシュテーブル形式)
// パターン1 (ハードコーディング). GDEQuizData quiz; // 取り出すデータの保存先. // "ニホンジカ"をキーにデータを取り出し、quizに保存する. GDEDataManager.DataDictionary.TryGetCustom("ニホンジカ", out quiz); Debug.Log(quiz.Description); // "ツノがある" とConsoleに表示される.
キーは手順2でゲームデータを作成した際に最初に登録した”Item Name”を使用します。
取り出したデータは GDE[Schema名]Data (ここではGDEQuizData) クラスのオブジェクトに保存され、
手順1で定義した Field Name (ここでは Description など)でアクセスできます。
今回はキーをハードコーディングしましたが、GDEItemKeys というクラスを使うことで、
ハードコーディングを回避できるようです。
// パターン2 (GDEItemKeysを使う方法). GDEQuizData quiz; // 取り出すデータの保存先. // GDEItemKeys.Quiz_ニホンジカ をキーにデータを取り出し、quizに保存する. GDEDataManager.DataDictionary.TryGetCustom(GDEItemKeys.Quiz_ニホンジカ, out quiz); Debug.Log(quiz.Description); // ツノがある とConsoleに表示される.
GDEItemKeys は手順2でデータを作成した後、手順3のクラス化を行うことで使えるようになります。
(手順3を先にやってしまうと GDEItemKeys に何も無い。なのでデータを追加したら手順3を必ず実行する必要があります。上記パターン1なら順番が逆でも問題なく動きます。)
データの呼び出し(全部取り出す場合)
上記では”ニホンジカ”をピンポイントで取り出しましたが、
まともに作るなら登録したクイズデータを全部取り出す必要があると思います。
(スクリプト上で一個一個キーを指定するのは非現実的ですよね)
Game Data Editorには手順1で定義したSchema名から全データキーを取り出すメソッドがあります。
List<string> allKeys; // スキーマからデータのキーリストを取得する. GDEDataManager.GetAllDataKeysBySchema("Quiz", out allKeys); // クイズデータを保存するリストを事前に作成. List<GDEQuizData> allItems = new List<GDEQuizData>(); // キーリストからキーを取り出す. foreach (string key in allKeys) { // キーを基にデータを取り出しリストに追加. GDEQuizData quiz; GDEDataManager.DataDictionary.TryGetCustom(key, out quiz); allItems.Add(quiz); }
これでallItemsに全クイズデータが保存されたので、順番に取り出して問題を表示したり、
といった事ができるようになりました。
※foreachはパフォーマンスに問題を抱えているようなので、最適化をするならforなどに書き換えたほうが良いと思います。
おまけ:データ呼び出し部分の汎用化
クイズデータ以外にジャンルデータをゲームデータとして管理したい場合、Schemaは2つになります。
手順3で作成されるクラスはSchema毎に作成されるので、GDEQuizData クラス以外に、
GDEGenreData クラスが作成されることになります。
上記のデータ呼び出しではGDEQuizDataクラスを直接使用していますが、
GDEGenreDataクラス用に同じようなメソッドを書くのはメンテナンス性の面で悪手かなと思います。
Schemaから自動生成されるクラスは、IGDEDataクラスを継承して作られているようなので、
Genericを使って汎化してみました。
T GetGDEData<T>(string key) where T : IGDEData, new() { T current = new T(); // キーに対応するデータを読み込む. if (!GDEDataManager.DataDictionary.TryGetCustom(key, out current)) Debug.LogError("Error reading quiz data!"); return current; }
以下使用例。
GDEQuizData quiz = GetGDEData<GDEQuizData>("ニホンジカ"); GDEGenreData genre = GetGDEData<GDEGenreData>("動物");
同様に、全データ取り出しもGeneric化しました。
/// <summary> /// スキーマ名からすべてのデータを取得する. /// </summary> /// <typeparam name="T">IGDEDataクラスを継承するクラス</typeparam> /// <param name="schemaName">スキーマ名</param> /// <returns>データリスト</returns> List<T> GetAllDataFromSchema<T>(string schemaName) where T : IGDEData, new() { List<string> allKeys; // スキーマからデータのキーリストを取得する. GDEDataManager.GetAllDataKeysBySchema(schemaName, out allKeys); List<T> allItems = new List<T>(); // キーリストからキーを取り出す. foreach (string key in allKeys) { // キーを基にデータを取り出しリストに追加. allItems.Add(GetGDEData<T>(key)); } return allItems; }
使用例。
List<GDEQuizData> quizzes = GetAllDataFromSchema<GDEQuizData>("Quiz");
こんなかんじでこのアセットを使用して、一応クイズゲームは形になりました。
一応遊べるし他のアセットなども駆使してスワイプなどもできるようにしたのですが、
なにぶん思いつきから作り始めた物なので、タイトル画面や音などを作る情熱が失われてしまい、
どうしようかなという状態になっています。
問題も30問程度は作ったので、せっかくだから公開したいと思っているのですが、
適当に仕上げた絵や音をお見せするのも申し訳ない気もしてううむといった感じです。
自分が興味を持てるものを作るというのが、個人制作においては重要なのかなと思ったりしました。
次回はGoogle Spread Sheetを使用したデータの登録方法について書きたいと思います。