Joël van der Werf
記事一覧

ゲームコンテンツをデータに:HydroのScriptableObject

セリフ、アイテム、クエスト、敵をC++から、インスペクターで編集できるリフレクション付きの定義ファイルとテーブルへ移しました。

10月末には、RPGにNPC、アイテム、ヒーロー、敵、クエストが揃っていましたが、すべてC++で書かれていました。NPCのセリフはキャラクターごとにif (name == "Farmer")のブロックが1つ。セリフを1行足すたびに、コードを編集し、ビルドし、再起動する必要がありました。室内マップや村が増えればそれは倍増し、セーブデータには長く使えるIDを持つコンテンツ(「ポーションを2つ持っている、長老と話した」)が必要です。

UnityにはScriptableObject、UnrealにはData AssetとData Tableがあります。Hydroには定義とデータテーブルができました。

モデル

  • 型はC++の構造体で、HY_DATAを付け、フィールドにはHY_PROPERTY、列挙型にはHY_ENUMを付けます。ジェネレーターがビルド時にリフレクションを生成します。
  • 定義(.hydef)は1レコード:ヒーロー1人、パーティー構成など。
  • テーブル(.hytable)はID付きの行:敵、ドロップ、クエスト、NPCのセリフ。
  • どちらもディスク上はYAMLで、アセットマネージャーのアセットとして扱われ、ネストした構造体、リスト、列挙型も含めて、コンポーネントと同じようにインスペクターで編集できます。

ゲームコードはData::Get<T>(handle)やData::GetRow<T>(rowRef)で読みます。ファイルや行がなければ、型のデフォルト値と1回の警告。クラッシュはしません。

シーンに触れずにコンテンツを移す

NPCのセリフをデータから取るために、すべてのシーンのすべてのNPCにスクリプトを追加するのは大変な作業です。代わりに、NPCのセリフはタグ内の名前でNpcs.hytableから探し、載っていないNPCにはDefaultの行を使います。シーンファイルは1つも変わりませんでした。看板、クエストのセリフ、各シーンのライティングのプリセットも同じ方法でデータになりました。

エンジンなしでテスト

ジェネレーター、シリアライザー、検索、編集操作には、ウィンドウもGPUも使わないヘッドレステストがあり、CIでもエージェントのサンドボックスでも動きます。データのバグは、プレイ中の空のダイアログボックスではなく、失敗したテストとして現れます。

それで可能になったこと

ヒーローの追加はテーブルに1行足すだけになりました。バトルのバランス調整はインスペクターで行います。そして、すべてのアイテム、クエスト、敵が長く使えるIDを持つので、セーブデータはIDで状態を保存できます。それが翌日のゲームセッションとセーブを可能にしました。

前の記事:エディタから.exeへ:初めてのスタンドアロンビルド次の記事:ルール、ビュー、ゲームセッション:ゲームコードの構成

お仕事のご相談はお気軽にどうぞ

東京在住です。Unity・C++・ゲームエンジン関連のポジション、C#・.NETのソフトウェア開発のポジション、そしてAIエージェントを活用した開発体制づくりに関心があります。英語・オランダ語・日本語(勉強中)で対応できます。