開発テーマ
本作では、二つの世界を切り替えるパズルアクションを制作しながら、Inspector 上でゲーム内の処理や演出を組み立てる仕組みを試しました。
ゲームとしてはシンプルな構成にしつつ、内部実装では、コマンド、Blackboard、Scalar、DynamicValue、MaterialFx など、後の制作にもつながる仕組みを多く検証しています。
Inspector 上で構築するコマンド
本作では、Interface を使って処理をコマンドとして定義し、SerializeReference を用いて Inspector 上で組み立てられる仕組みを試しました。
これにより、C# ファイルを直接編集せずに、テキスト表示、カメラ移動、Material パラメータの変更などの演出処理を構築できるようにしました。
また、ScriptableObject と組み合わせることで、Inline 編集だけに依存せず、再利用しやすい形でもコマンドを扱えるようにしています。
マップ情報も ScriptableObject で管理し、ステージ内容をコードから分離することで、レベルデザインの調整をしやすくすることを目指しました。
一方で、Inline でコマンドを組み立てる構成は、処理の流れが Inspector 内に分散しやすく、全体の把握が難しくなる課題もありました。
特に、実行順序や条件分岐が増えると、どの処理がどのタイミングで実行されるのかを追いにくくなり、デバッグが難しくなりました。
Blackboard と状態管理
本作では、Entity ごとに状態を保持する仕組みとして Blackboard を導入しました。
Blackboard は、コマンドの実行結果やゲーム内の状態を保存し、複数のコマンド間で情報を共有するために使用しました。
これにより、演出や分岐処理をデータとして扱いやすくなり、コードに直接依存しない形でゲームロジックを組み立てられるようにしています。
また、Blackboard に保存された一部の値は Easy Save 3 を使ってセーブデータに反映できるようにしました。
ただし、WebGL 環境では安定性に課題があり、セーブ周りは未完成な部分も残りました。
Blackboard は柔軟な一方で、値の型管理、アクセス経路、更新タイミングを整理しないと、どこで値が変化したのか分かりにくくなります。
また、boxing や頻繁な参照が発生する箇所では、パフォーマンス面にも注意が必要でした。
Scalar と DynamicValue
Blackboard に近い仕組みとして、float 値を扱う Scalar も作成しました。
Scalar は、Base 値、Add 値、Mul 値を組み合わせて最終的な数値を計算する仕組みです。
ステータスや補正値のように、複数の要素から一つの値を求めたい場面で使うことを想定しました。
また、コマンドのパラメータを柔軟に扱うために、DynamicValue<T> も作成しました。
これは、直接入力された値だけでなく、Blackboard など別の情報源から値を取得できる仕組みです。
例えば、あるコマンドの引数として DynamicValue<float> を使うことで、固定値を渡す場合と、実行時に Blackboard から値を取得する場合を同じ形で扱えるようにしました。
一方で、DynamicValue<T> は便利な反面、型安全性、Inspector 上での編集しやすさ、実行時コストに課題がありました。
Editor 拡張も最低限の実装に留まったため、実際の制作では扱いづらい場面もありました。
MaterialFx と演出
Material のパラメータをコマンドから操作するために、MaterialFx も作成しました。
これにより、Fade、BlendColor、画面全体の色変化などの演出を、コードを直接編集せずに調整できるようにしました。
カメラ演出やテキスト表示と組み合わせることで、イベント中の見た目の変化を Inspector 上から構築できるようにしています。
また、ComputeShader を使用してノイズテクスチャを生成し、それを MaterialFx 側で合成する仕組みも試しました。
これにより、より複雑な画面効果を作ることができました。
ただし、ComputeShader は WebGL では使用できず、対象プラットフォームによっては無意味な実装になってしまいました。
また、ノイズ生成の負荷やビルド時間への影響もあり、短期間制作のゲームに導入するにはコストが高いことも分かりました。
ゲームデザイン上の課題
本作では、二つの世界を切り替えてゴールを目指すというシンプルなコンセプトを設定しました。
短期間で制作するうえでは、遊びの軸を絞る意味で有効でした。
しかし、実際にはレベルデザインに苦戦し、世界切り替えを使ったパズルとして十分な面白さを作りきれませんでした。
多くのステージがチュートリアルの延長のようになり、プレイヤーに考えさせる場面や、解けたときの達成感を十分に用意できなかった点が大きな反省です。
この経験から、パズルゲームではシステムを作るだけでは不十分であり、そのシステムから面白い問題を作れるかどうかが重要だと学びました。
学んだこと
本作はゲームデザイン面では課題が多く残りましたが、技術面では多くの検証を行ったプロジェクトでした。
特に、以下の点を学びました。
- Inspector 上で処理を組み立てる仕組みは、演出やイベント制作に有効である
SerializeReference は柔軟だが、Editor 上の見通しやデバッグ性に課題が出やすい
- Blackboard のような汎用データストアは便利だが、型管理と更新経路を明確にしないと複雑化しやすい
- DynamicValue のような仕組みは強力だが、Editor UX と実行時コストまで含めて設計する必要がある
- ComputeShader や高度な描画処理は、対象プラットフォームと制作期間を考えて導入する必要がある
- パズルゲームでは、システムそのものよりも、そのシステムを使ったステージ設計の質が重要になる
反省点
本作では、新しい仕組みを多く導入した一方で、ゲーム本体の面白さを作り込む時間が不足しました。
特に、コマンド、Blackboard、Scalar、DynamicValue、MaterialFx などの技術検証に比重が寄りすぎ、レベルデザインの試行錯誤に十分な時間を使えなかった点が課題でした。
今後は、技術的な仕組みを作る段階と、ゲームとして面白くする段階を分けて考え、早い段階でステージの面白さを検証する必要があると感じています。
この反省は、後のプロジェクトで、データ駆動の仕組みや Inspector 上の制作フローを整理するきっかけになりました。