気づけばツール漬け

3D,2Dのツールを色々使ってみた記録を書いていきたいです。

「ROTATE BREAKOUT」制作メモ 前編

f:id:mi-zmix:20210412204630p:plain

第15回UE4ぷちコン応募作「ROTATE BREAKOUT」の制作メモです。使ったUE4は、4.26.1です。
前編は企画案についてと、各要素(ブロックとか回るステージとか)について書きます。後編は絵とその他の事について書くつもりです。

応募動画はこちらです。

www.youtube.com

パッケージにした物を個人のDropBoxに上げました。よかったら遊んでみてください。
(起動直後のプレイは、とても重くなります。一度アイテムなどを全部出現させてからじゃないと、まともに遊べないかもしれません)
↑ 私のPCのSSDプチフリーズしていただけだったぽいです。でも重くなったらすいません。
(安全ではないアプリという表示が出ると思いますが、「詳細情報」のクリックで実行できると思います)

drive.google.com

企画案について

「かわる」と聞いて最初は「何でもありか?」と思ったのですが、変わることに大きな意味がある何かをやりたいなって考えました。

ゲームのルールを変えて何かしたかったのですが断念しました。ルールを変えると、変わったルールを説明しないとならないので難解になりがちです。説明がいらない既存の何かを変えた感じが良いかと考え、ブロック崩しを思いつきました。前々から、普通ではないブロック崩しが何かできないかと思っていたのでやってみることにしました。

今回のゲームは、全8ステージ構成にしました。もう少し長くしても良かったのですが、長いとしんどいので8ステージに収めました。あと、このゲームはステージバリエーションが作りにくいのです。なぜかといえば、背景が回転するためブロックは背景のすみっこにまでピッチリ配置できません。配置できる場所は中央寄りの狭い範囲に限られてしまいます。ステージの回転と一緒に、ブロックも回転させれば解決できますが、それはやめておきました。ブロックの配置が変わらずに、ステージのミスになる場所だけ変わるほうが面白いかと思ったからです。実際、画面の上の方にブロックが残っているとき、ミスになる場所が上になっている時の緊張感は面白いと思いました。

残念なこととしては、ブロック崩しの面白さの大きな要素である連続消しができないことです。端のブロックを崩してから上方にボールを送り、天井とブロックの間で反射して連続で消えていくという様子は、積極的に狙ってやってみるほど面白いはずです。その後ものすごい速さで降りてくるボールを捉えきれなくてミスになったりしますが。(ステージ5,6で、その感覚が表現できないかちょっと試してみました)

基礎部分の構造

基礎はブロック崩しなので簡単でした。数多くのブロック崩しの作例があるので参考にしつつ進めていきました。
ボールはプロジェクタイルムーブメントで飛ばしています。重力をなくし反射は1にしました。反射したときの摩擦は0に設定しました。最大速度は2400にして、それ以上速度があがらないようにしました。2400は、もう反応できない速度だと思います。

f:id:mi-zmix:20210412205617p:plain

イニシャルスピードは0になってますが、コンストラクションスクリプトで速度と方向を設定しVelocityに渡しました。

f:id:mi-zmix:20210412210035p:plain
あと、平面のコンストレイントの設定をして、Z方向に飛んでいかないようにしました。

f:id:mi-zmix:20210412205838p:plain

ボールは、壁やブロックで跳ね返るたびにスピードをちょっとずつ上げるようにしました。プロジェクタイルムーブメントの、OnProjectileBounceイベントを使って、現在のVelocityに、1.015を掛け算しています。小さい値ですが、けっこう加速します。

f:id:mi-zmix:20210412235432p:plain

プレイヤーキャラの棒には、キャラクタームーブメントなどのムーブメントコンポーネントは使いませんでした。インプットイベントからの値に、移動量を想定した値とデルタセコンドを掛け算して、Set Actor Locationで動かしました。移動量はあとで変更できるように、変数にして外から見えるようにしておきました。
間にあるマクロは、ゲームの状態のチェックと最初の一発目を打ったかどうかを判定してます。メインのゲーム以外(レベルの切替時とかリザルトとか)では動けないようにするためです。

f:id:mi-zmix:20210412210332p:plain
回転も同じように、角速度を想定した値とデルタセコンドを掛け算して、Add Actor Local Rotationで回しました。Bool値で回転の方向を変えられるようにもしました。

f:id:mi-zmix:20210412210630p:plain

プレイヤーはスタティックメッシュに BlockAllDynamic のコリジョンを設定しました。ボールがあたった時は素直に跳ね返しています。あたった位置によって角度を変えるという処理はしていません。プレイヤーが回転できるので、角度を変える処理は邪魔になると思い入れませんでした。
先端にダミーのボールメッシュをおいて、最初の一発目を打つまではこれを表示しておき、一発目が打たれると同時に消しました。
まわりにあるカプセルコライダは、ブロックとの接触を判定するためのものです。ブロックと接触してるときは回転できなくしてます。

f:id:mi-zmix:20210412210905p:plain

ブロックはボールがあたったら消えるだけです。シンプルな方が雰囲気が出るきがしたので、エフェクトを出すのはやめました。消える直前にアイテムを出すようにしました。アイテムについては後述します。

 

 独自部分の構造

ローテーションブロック

ローテーションブロックは、ブロックBPのベースからチャイルドBPでつくったものの、ほとんど違う物になったので通常のブロックと分けて作りました。ボールがあたったときに回転する方向は、Boolで切り替えられるようにしました。
回転方向の矢印絵と、鍵アイコンの絵はメッシュで重ねておいて、表示非表示を切り替えました。
このブロックは別のタグを設定して、ステージクリア判定の対象外にしました。ローテーションブロックを消さなくてもステージクリアできます。ただし、ローテーションブロックは消すと1000点入ります。

f:id:mi-zmix:20210412211314p:plain

ローテーションブロックにボールがあたると、ブロックが持っているステージの回転方向のBool値とともにゲームモードに通知します。ボールがあたったらまずコリジョンをなくして、短いライフスパンで消すようにしました。

f:id:mi-zmix:20210413000054p:plain

ステージの構造

ステージを回転させる指示は、ローテーションブロックからゲームモードを通して、ステージBPに送られるようにしました。

回転はタイムラインで動かしました。回転がおわったら、回転後の角度を新たな基準にするように変数を上書きしました。

f:id:mi-zmix:20210412211833p:plain
f:id:mi-zmix:20210412211929p:plain

なにもせずに回転の通知だけ送っていると、ステージの回転中にあらためて回転の通知が来た場合、ガクガク回転してしまいました。なので、回転中は他のローテーションブロックを無効にしました。回転がおわったらゲームモードへ通知して、回転ブロックを通常にもどすようにしました。(ステージの開始とともに、ローテーターブロックをTagで検索して配列に入れています)

f:id:mi-zmix:20210412212234p:plain

ステージをクリアした時やリザルトへ移行する時は、カスタムイベントの ForcedStopRotation でステージの回転を強制的に元に戻すようにしました。

バリアの出現もタイムラインで動かしました。バリアの指示もゲームモードからのイベントディスパッチャを受け取って動かしました。壁を下から上げて、一定時間経過したら下ろすというシンプルなものです。

f:id:mi-zmix:20210413212104p:plain

ボスの構造

ブロック崩しの進化のなかで、ボスはわりと欠かせない感じなので入れてみました。耐久力が高いだけの大きなブロックになりがちですが、ステージの回転というギミックがあるおかげで、一味違うものになったかなと思っています。テーマが「かわる」なのでカエルだね、と3秒で考えました。
目とほっぺのメッシュは、普段は非表示で回転がはじまったら表示するようにしました。

f:id:mi-zmix:20210412212603p:plain
ボスを倒してもステージクリアにならないのはちょっとだめかな? と思いましたが、特別な処理が増えてデバッグもしにくいとおもったのでやめておきました。ボスを倒したらブロックが一個出るのはクリア判定のためですw

アイテムについて

アイテムは3種類にしぼりました。よくあるアイテム例として、プレイヤー棒が伸びるのは回転した時に引っかかりやすくなってしまうのでボツです。短くするのは、ただの迷惑なのでこれもボツです。弾がうててシューティングできる要素は、そこまでストレスたまるような展開でもないだろうということでボツです。

アイテムはまずプレイヤーとオーバーラップするので、プレイヤーへアイテムの種類と設定データを送り、プレイヤーからゲームモードへ通知して、ゲームモードからステージとボールへイベントディスパッチャで通知しました。ステージとボールは、ゲーム開始時からゲームモードをキャストして参照しているので、この流れにしました。

f:id:mi-zmix:20210412213057p:plain

スピードダウン

最初は、現在の速度から半分に落とすという仕組みにしていたのですが、スピードダウンを連続でとってしまうと、初期速度より遅くなってしまうことがあったのでやめました。どんなに速い状態でも、初期速度に戻すという処理にしました。このおかげで、かなり助かるアイテムになっちゃったと思います。
↓スピードを落とす関数の中。ヴェロシティをノーマライズして初期速度を掛け算しました。

f:id:mi-zmix:20210412213425p:plain

マルチボール

メインのボールからサブのボールを3個スポーンします。
X軸方向は速度分の値にして、Y軸方向をランダムでバラけるようにしました。

f:id:mi-zmix:20210412213730p:plain

サブのボールには別のタグをつけて、プレイヤーのミスの判定から除外しています。ライフスパンを設定して時間で消えるようにしました。ステージの外に出ても、する~っと流れていきますが、時間が来たら消えるはずです。
ときどき、マルチボールのアイテムを取ってもサブのボールがスポーンされないことがあります。試しにSpawnのReturnValueにIsValidノードをつなぎ、Is Not Validの先にPrintStringをつないだら表示がでたのでパルスは流れてきてると思うのですが謎です。

f:id:mi-zmix:20210412213812p:plain

バリア

ブロックするメッシュを上げ下げするだけの単純なものです。最初は5秒で設定していましたが、短すぎると感じたので7秒にしました。たった2秒の差ですが大きく感じました。10秒も試しましたが長すぎでした。

f:id:mi-zmix:20210412214013p:plain
通常のブロック崩しであれば、画面下側は全部ミス判定になるところですが、その形状でプレイしてみると、凄まじく難しかったので下側にも少し壁を置きました。この壁は一応ON,OFFできるようにはしておいたのですが、結局ONのままにしました。

 

 前編は以上です。後編に続きます。
後編書きました。

mi-zmix.hatenablog.com