BlenderのGeometryNodesでゲームを遊べるようにした
Simulation Input / Output ノードのおかげでもはや何でもできるようになってしまったので、とりあえずゲームでも作るか、ということで作ってみました
洞窟の中を紙飛行機が飛んでいく、というようなワンボタンアクションゲームになっています。
この記事では実際にノードを見せつつ、各工程で「大体こんなことをやっています」というのをざっくりと解説していきます。
環境について
今回「Simulation Input」「Simulation Output」という2つのノードを使用するのですが、2022年12月5日現在このノードは開発中の機能で、正式リリースされている機能ではありません。
以下の記事などを参考に Blender 3.5.0 の Geometry Nodes Simulation のブランチのBlenderをダウンロードする必要があります。
ノード全体像
ノードはこんな感じです。左上がメインのGNで、それ以外が呼び出されるノードグループです。
メイン部分は前半でシミュレーション(ゲームの処理)を行い、後半でUI表示を行います。
シミュレーション部分(ゲーム処理パート)
シミュレーション部分では以下の3つのグループが処理を行います。
シミュレーション部分は前処理を行う「PreProcess」
紙飛行機の処理を行う「Airplane」
上下の壁の処理を行う「Rocks」
前処理(PreProcess)
この工程では、
ジオメトリを「紙飛行機」と「上下の壁」に分離
ゲームオーバーの判定
紙飛行機の高さの取得
を行います。
紙飛行機と上下の壁はいずれもジオメトリ上ではインスタンスとして扱っており、紙飛行機のインスタンスのインデックスが常に0番をとるようノードを組みました。
そのため(少しアドホックですが)ジオメトリ分離ノードの「選択」にインデックスを繋ぐだけで紙飛行機と壁が分離できるようになっています。
ゲームオーバーの判定は「壁のインスタンスが少なくとも1つある」かつ「紙飛行機と最も近い壁との距離が1m未満」という条件のもと行います。
また、紙飛行機の高さは属性統計ノードから取得しています。
紙飛行機の処理(Airplane)
この工程では、
スコア計算
紙飛行機の回転
紙飛行機の上下移動
を行います。
スコアの計算は、名前付き属性格納/名前付き属性ノードを使って、「SCORE」という属性(Attribute)を定義し、毎フレーム加算することで行います。
紙飛行機の回転は入力のブーリアン値に従い、上を向くか下を向くかをスイッチノードで決定します。
また、インスタンス回転ノードに繋ぐ前にスケールを0.4倍程度かけておくことで一瞬で回転せず、若干滑らかな動きになるようにしています。
紙飛行機の上下移動も入力のブーリアン値から移動値をスイッチしています。
上下の壁の処理(Rocks)
この工程では、
壁ブロックの生成
壁ブロックのスクロール
画面外に出た壁ブロックの削除
を行います。
今回、壁ブロックの生成は毎フレーム行う必要はないため、10フレームに1度だけ生成が行われるよう、現在のフレーム数を10で割ったあまりが0の場合のみブロックが生成されるようにノードを組んでいます。
ブロックの座標はノイズテクスチャによってランダムに配置されるようにしていますが、シーンタイムをシード値にすると毎回同じ配置になってしまいます。
これを防ぐために、ノイズテクスチャにはシーンタイムの他に紙飛行機の高さを渡すようにしてプレイヤーの操作によって違う配置のステージが生成されるように工夫を行っています。
また、難易度が変動しないと延々とプレイが続いてしまうので、時間が進むにつれて幅が狭まるような調整もここで行っています。
壁ブロックのスクロールはインスタンス移動ノードで行っています。
画面外に出て不要になった壁ブロックの削除は、インスタンスのX座標が-15以下かで判定し、ジオメトリ削除を行っています。
UI表示部分
UI表示部分では、
ゲームオーバーの判定と、ゲームオーバー画面の生成
背景の生成とSCORE属性の登録
スコア表示
を行っています。
ゲームオーバー画面はテキストと、画面をぼかす板ポリを生成します。
また、スコア表示でもテキストを、背景でも板ポリを生成します。
ここでは以下2つのグループを作成してテキスト生成や板ポリ生成が使い回せるようになっています。
背景のスクロールはGeometryNodesではなく、シェーダーにまかせています。
しかし何らかの手段でスクロールの具合を指定しなければならないので、ここでスコアを背景板ポリの属性として登録しておくことでシェーダー側から読み出せるようにしています。
グラフィック面
紙飛行機や上下の壁ブロックは普通にモデリングしていきます。
リアルタイムにプレイを行いたいのでレンダーエンジンはEeveeを使用します。
今回のようなゲームデザインではブルームやスクリーンスペース反射を有効にすると見栄えが良くなりそうです。
水晶のマテリアルも光に照らされてキレイな見た目になるように調整します。
紙飛行機の手前にポイントライトを設置して、洞窟探検っぽいライティングを演出しました。
おわりに
これでひと通り解説できました。
Simulation Input / Output ノードは本当に強力ですね。工夫次第で本当に何でもできそうです。
この記事とは直接関係ありませんが、普段からGeometryNodes芸人をやっていて、色々記事にしているので、興味があれば是非そちらも御覧ください。