本日のテーマは『スイカゲーム』風の落ちものパズルを作ろう です
ゲームには成功や失敗で終了する条件がつきものですね。本記事はゲームの状況を監視して、ゲームオーバーにする仕組み をつくります。(画面は次回)
URSuika UnrealEngine製のスイカゲーム風3D落ちものパズルゲーム – BOOTH
無料です(Windowsのみ)遊んでみてください。
どうなったらゲーム完了?
スイカゲームなどの落ちものパズル系は、クリア条件はあまりなくて、ゲームオーバーになる条件は上まで積みあがったら が多いかなと
では、積みあがったかどうかは誰がどうやって監視すればよいでしょう?
テトリスやぷよぷよなどの2Dの落ちゲーでは、落下し終えて動きが止まったタイミングで、ゲームマスターが盤面の状況をチェックして、基準の線を越えていたらゲームオーバー・超えていなかったら次の持ち玉を出すという流れが一般的かなと思います。
高さ判定1配列チェック
2Dなら盤面の状況を2次元配列変数で管理していて、何行目に中身があるか、を見るだけOKです。
3Dでも1マス単位で動くゲームを作る場合は同じ作戦が取れるでしょう。
しかし、物理エンジンを利用してマス目がない今回のようなゲームでは、配列作戦は少し難しくなります。
一定サイズの箱型のセンサーを等間隔に並べて管理する方法になるかと思います。

AIキャラのナビメッシュはこの考え方なので、場合によってはこの作戦もありですが、ちょっと難しいので今回は捨て
高さ判定2 最大高更新
ゲームモードやレベルBPに玉の高さを管理する変数を用意して、持ち玉が落下し終えたタイミングで最高値更新したか判定することもできます。
これは管理する情報が最高値1つだけで最も処理効率がよい作戦ですね。
ただし、スイカゲームの場合は、落ちたあとのフルーツもまだ移動する可能性があるので、固定されて盤面を評価するというタイミングがないというか常にある状況で、
すべてのフルーツの高さを常に監視することになります。

なので、最高値かどうか比べる処理は無駄で、直接ゲームオーバーライン越えたか比較するだけでOKですね
高さ判定3 コリジョン
常に監視しなきゃいけないなら、コリジョン(みえない箱)を設置して、当たり判定を行う作戦も考えられますね。
これは簡単比較的簡単そうに思うので有力です。
ただし、持ち玉を箱の中に落とす段階で判定されちゃうと箱に入れる前にゲームオーバーになってしまうので、入るときと出るときを分けて処理する必要はありそうです。
高さ判定4 センサー
赤外線センサーのイメージで、ライントレースなどのRaycastを照射して侵入者を検知するみたいな仕組みもあります。

貫通させられるので、横にどれだけ詰まっているか密度を調べるみたいな用途にも使える作戦です。
これもコリジョンと同じく入るときと出るときの処理分けが必要ですね。
今回の採択案:高さ判定2のアレンジ
今回は、あふれ出て外にこぼれ落ちたらゲームオーバーな仕様とします
これは、
- 1は新しい技術が必要で大変そう
- 3や4の方法だと入るときと出るときの判定処理分けなどが少し面倒そう
- 一旦上に跳ね上がっても、ふたたび容器内に落ちればセーフなほうが楽しいかなとおもった
- 3や4のアレンジで容器の外を監視することもできるが、どのくらい遠くまで飛んでいく可能性があるか気にする必要あり
ということで、玉自身が今どの高さにいるかを常にチェックし、脱出成功したら(プレイヤー的には)ゲームオーバーとする方針としてみます。
キルZ
容器の外に落下させた玉の位置をモニタリングすると、どんどん落ちて行きます
米粒を過ぎて見えなくなってもレベル上に存在しているのでどんどん処理負荷が上がっていきます。
この、どこまでも落ち続けるのを止める手段として設定のワールドセッティングに「キルZ」という設定があります

デフォルトではマイナスのかなり大きな値になっているのでなかなかそこまで到達しません

UEはcm単位なので-10kmくらいですね
これをたとえば0に変更すると、落下させた直後に速攻で消えました
容器のほうを原点より下に下げたのでこれでは遊べませんね
ではマイナス1000くらいにしてみましょう
容器の底では消えずに、外に落とせば消える状態にできましたか?
こんなふうにお手軽に削除処理をできます
ですが今回は、この仕組みは使わずに大きめの値に戻して、独自の落下判定を作ってみましょう。
落下判定
高さ判定3案のように、地下に大きなコリジョンを作って、それに何かぶつかったら とすることもできますが、
すでに言及したように、どのくらい遠くに落ちるかわからないので、大きなコリジョンにする必要がありますね。
今回は玉 BP_Fruit 自体に、自分が落ちたらゲームオーバーにする機能をつくりましょう
落ちたことを知る方法もいくつか考えられますが、今回は自身の位置情報をモニタリングしてみましょう
BP_Fruit > イベントグラフ

常にやる処理はティックというイベントで行います。無効になっていると言われて暗くなっていますが、線をつなぐと有効になります
まずGet Actor Location で自分自身の位置を取得しましょう。高さが知りたいので分解してZ成分を取り出します

これが指定の高さより小さかったらの判定がしたいので「Z<基準点」ですね
基準の高さは-1000にします。
Bで条件分岐をつなぎます。Trueの成立したときが落下したときなので、とりあえずデバッグ表示でゲームオーバーと表示してみましょう

出ましたね

毎フレーム計算しているので一旦落ちたらひたすら表示されます
キルZのかわりに、自分で自分をDestroy Actorしましょう

玉は消えて、GameOver表示は1つの玉につき1回表示されるだけになりましたね
いまはそのまま遊べちゃいますが、ゲームオーバー状態になったら、自機を操作できるのを無効にしたり、「Game Over」などの表示を出したりなどが残件ですね。
画面表示は得点計算とまとめてやりましょう
ゲームマスターは誰?

今時点はフルーツ1つ1つがゲームオーバーを管理している状態で、同時にたくさん落ちたりすると重複したりなどの問題があるのと、今後得点計算するときにも総合点を各フルーツが持っているのは効率が悪そうなので、ゲームの状態を管理する役が必要ですね。
一般的には、その役は、レベルBPやゲームモード、ゲームインスタンスなど、ゲーム実行中に常に存在しているブループリントが担当する場合が多いかと思います。
が、今回の仕様であればプレイヤーキャラクターも常にいるため、プレイヤーが担当するようにして触るBPを少なくしましょう。
BP_ThirdPersonCharacter > イベントグラフ
add custom eventです。ゲームオーバー処理を作りましょう。ひとまず「Game Over」のデバッグ表示をお引越しだけします

フルーツ側はこのイベントを呼び出しましょう
BP_Fruit > イベントグラフ / Tick

プレイヤーキャラクターをキャストするいつもの処理です。これでもとと同じ処理だけど、プレイヤーキャラ側でゲームの状況に応じた機能追加がしやすくなりました
あと、これで問題はありませんが、なんども同じ処理をしているので、少し効率を上げてみましょう
プレイヤーを探してキャストする処理をBeginPlayで1回だけ探すと効率がよさそうです
プレイヤーキャラの情報を変数に保存します
BP_Fruit > イベントグラフ / BeginPlay

プレイヤーが生きてる限りはこれでやり取りできるので、今回のゲーム仕様なら問題ありません
キャストノードの代わりにこの変数をつなげばOKです
BP_Fruit > イベントグラフ / Tick

ほかの箇所も同じように変更します
BP_Fruit > イベントグラフ / Hit

動作に問題ないかも一通り確認しましょう
コメント