ゴマちゃんフロンティア

アザラシが大好きなエンジニアの開発日記です

「第10回 Unity1週間ゲームジャム」に参加しました!

time 2018/11/26

今回は11/19~25の間に行われた「Unity1週間ゲームジャム」に初参加したので、そのお話になります!
ほぼ完全に独学ながらUnityは4.1の頃から触っていたのですが、「1週間ゲームジャム」なるものがあることを知ったのはかなり最近だったりします。

今回のお題は「10」でした。
真っ先に思いつくのは「10秒間で何かする」とか「何かを10個集める」みたいなものですね。
初参加ということもあったので、シンプルにまとめ上げられるゲーム性で行くことにしました。

ゲーム紹介

「ばくれつうさぴょん」というタイトルで投稿しています。
https://unityroom.com/games/bakuretsu_usapyon

「10秒以内に箱をできるだけ壊す」というゲームです。箱を壊すとスコアが入ります。

赤い木箱は壊すと爆発し、周囲の箱を破壊します。
鉄の箱は破壊できませんが、縦攻撃で吹き飛ばすことができ、当たった木箱をまとめて破壊します。
どちらも普通に破壊するよりスコアが追加で加算されます。

うさぴょん (プレイヤーのウサギ) のアクションは基本的な8方向への移動と2種類の攻撃です。

左クリックでハンマーを叩きつけて攻撃します。
攻撃中は足が止まるので、時間の限られるこのゲームでは使い勝手はよくないのですが、鉄の箱はこの攻撃でしか吹き飛ばせません。
回転攻撃では5ヒットさせる必要のある赤い木箱も、叩きつけなら一撃で破壊できます。

右クリックでハンマーを横に振り回して攻撃します。回転して攻撃するので周囲を一度に攻撃できます。
また、移動入力中に使用するとその方向に移動しながら放つことができます。連発すると大量の木箱をまとめて破壊できます。
反面、赤い木箱の破壊には時間がかかり、鉄の箱を吹き飛ばせません。

私が開発中にプレイして出した最高スコアは283です。
箱の配置は毎回固定なので、移動ルートや鉄箱を吹き飛ばす方向をしっかり考えればもっと行けると思います。

各日の様子

1日目 (月曜日)

お題が発表された後、すぐにゲームのアイデア考案と設計に入ります。
ちょうどSkypeで兄と会話している状態だったので、2人で意見を出し合い、自分の技量でいけそうなものを選定しました。
新しくUnityプロジェクトを作り、フォルダ構成やシーンを整理してその時は終了。

1日目の帰宅後は基本的なゲームシステムの完成を目指して開発します。
事前にゲーム内容を技量に合わせてフィルタリングしたこともあり、本ブログで紹介してきた内容の寄せ集めでほとんど実現できる上、「ジャンプ」や「敵キャラクターの行動制御」みたいな要素もないので、この日だけでベースとなる部分の作成を終えることができました。
今思えば初参加な上に仕事の繁忙期とも重なっているため、シンプルだけど確実に実現できそうな内容をチョイスしてよかったです。作ったことがないようなゲームに挑戦するのも楽しそうですが、それは次の機会にとっておきます。

2日目 (火曜日)

1日目からいい感じのペースで作業が進んだので、2日目以降はちょっと気持ちに余裕を持つことができました。
2日目はタイトル画面やスコアの記録、ゲーム終了時の処理などを実装し、ゲームとしての体裁を整えました。

この時点で一度WebGLでテストプレイをしてみたところ、「木箱をなるべく多く壊す」というゲームコンセプトに対し、木箱を壊しまくると破片が増えて処理落ちが頻発するという問題が発生してしまいました。

対策として破壊後の破片を一定時間後に削除するようにしました。破片が残りっぱなしになっていた方が壊した感あってよかったのですが、こればかりはどうしようもないですね…。

3日目 (水曜日)

私の会社は毎週水曜日を「フレッシュアップデー」と定めており、所謂定時退社日なわけですが…。無論定時で帰れるわけもなく、急な仕事と私的な事情もあって1時間弱しか作業ができませんでした。
それでも1週間という限られた時間しかないため、開き直ってモデリングやエフェクト面を強化しました。

エフェクトは以前構想していたゲーム用に作ったものを参考にしました。殺伐とした必要は全くないので漫画っぽい衝撃波と星が出るポップな感じにしてみました。

次に武器です。さすがにニンジンブレードで木箱を壊すのは見た目的にアレなので、オーソドックスなハンマーを作りました。

4日目 (木曜日)

日付だけを見ればそろそろ折り返しの4日目です。
帰宅はそこまで遅い時間ではありませんでしたが、明日遠出の予定がある関係で早めに寝たため、実作業時間はそこまで多くなかったです。

4日目はまず木箱の (負荷的な意味で) 軽量化を図るべく、モデル上の破片を結合して量を1/2にしました。これだけでもかなりマシになりますね。
古い状態の木箱は1箱あたり84個の板で構成されているため、そのまま破片としてばらけさせるには多すぎた感はあります。

次に「爆発する箱」を作成しました。破壊されると同時に攻撃判定を発生させ、周囲の木箱をまとめて壊せるという代物です。
エフェクトはアセットストアの無料のものを使用しましたが、派手すぎて重くなってしまうため、パーティクルの最大生成数を減らして使用しました。

5日目 (金曜日)

朝早くから遠出していた上、帰ったら頭痛で寝込んでいたため、4日目に続いてあまり作業が行えませんでした。
まずはゲーム終了後のスコア表示から。

タイトル画面に戻るまでの3秒ほどは画面中央にでかく表示するようにします。
割と重要な要素なのに5日目までノータッチだったというのが今では信じられないですね。

次に「吹き飛ばせる鉄箱」を作成しました。

吹き飛ばした先に箱があればまとめてなぎ倒すことができます。前述した爆発する箱に当たれば更に連続して破壊できることもあります。
物理演算で吹き飛ばしているので予測しにくいのが特徴です。飛ぶ方向と強さが完全固定だと最適解が固定化されてしまうので、この手のゲームとして好ましくありません。

6日目 (土曜日)

5日目までで欲しい機能は大抵実装できましたが、ゲームとして見たときにいくつか問題点や粗削りな部分があったので、そのあたりを順次対応しました。
割と致命的なものとして、相変わらずゲーム画面の動作が遅く処理落ちが頻発するというものがあったので、4日目で調整した以上に箱の軽量化を目指すことにしました。
具体的な対策として、「分割された箱を破壊時にバラバラにする」ではなく「1オブジェクトのみの箱を用意し、破壊時に分割された箱にすり替えてバラバラにする」ように変更しました。

分割された箱は上の画像のようにオブジェクト数が多いので、シーン上に大量に配置するとそれだけで重くなってしまいます。破壊されるまでは分割させておく必要はないので、1オブジェクトにまとめた箱を配置しておけば負荷を減らせますね。

上記の対応を入れても箱を一気に壊しすぎると重かったので、破壊時の破片の量を調節するようにしました。LINQで子オブジェクトの破片を半分ほど消してしまいます。
元々破片が少し多すぎると思っていたので、減らしたらむしろ適量になりました。動作も挙動できるレベルになったので一石二鳥ですね。

あとはタイトル画面のタイトル表示背景にうさぴょんのシルエットを配置しました。
作り方は超簡単で、「Blenderでライト関連のオブジェクトを消してF12でレンダリング」すると以下のような結果になるので、適当にトリミング&背景の透過対応をしてUnityへインポートするだけです。

せっかくの土曜日ですが、この日も家族であれこれやっていたので、他に細かい修正をしただけで終わりました。

7日目 (日曜日)

最終日です。期限ギリギリで提出するのは避けたかったので、余裕を持って提出するべく朝から作業を行いました。

手始めに鉄箱を吹き飛ばした際の挙動を修正。
ハンマー振った時の攻撃判定用オブジェクトのTransform.rotationが歪な値になっていたため、プレイヤーキャラの向きと合わせるようにします。
ただ、振り下ろすモーション故に箱に対して叩きつけるような力が働いてしまい、大きくバウンドする挙動になってしまいました。なので素直にプレイヤーから見た箱の方向を算出し、その方向に飛ばすようにしました。
具体的には「箱の位置 – プレイヤーの位置」のベクトルでRigidbody.AddForce()を呼び出します。

これで真っ直ぐ飛んでくれるようになりました。物理的にはおかしいですが、ゲーム的な都合を優先した感じですね。

次にタイトル画面のゲームスタート前に簡単な操作説明を入れるようにしました。

これは家族にプレイさせたところ「操作方法が全然分からん」と指摘されたためです。投稿時のゲーム紹介に書けば良いかと思っていましたが、1ゲームとして見た場合は不親切であることは確かなので入れることにしました。
ちなみに1回プレイした後はタイトル画面に戻ってきますが、2度目の説明は不要かと思うので省略するようにします。具体的には「トップスコアが1以上」の場合は表示しないようにしました。

あとはステージの調整です。
無機質に箱が並んでいても味気ないので、少し並べ方を変えたり、赤い木箱や鉄箱の量を増やしてみました。

無意識に箱をコピペしていたら、スペースインベーダーに出てきそうな敵の形になっていました。お題に沿って「10」の字に配置しても面白かったかもしれませんね。

最後に「隠しコマンド」を搭載しました!
ゲーム中にあることをするとキャラクターがパワーアップします。ヒントは「立ち止まって特定のキーを10回」です!
是非探してみてください!

ここで一度ビルドしてWebGLで確認しますが、やはり箱を一気に破壊したりすると重くなります。
ここまで来てから仕組みを変えるのは難しいとなると、箱の破片数を減らすしかないので、1箱からランダムに選定した10個の破片以外はLINQで削除してしまうようにしました。見た目上の爽快感は薄くなってしまいますが、快適な動作には代えられません。

しかし最後の最後、unityroomに投稿した後に「Maximum call stack size exceeded」というエラーが発生。
非常に焦りましたが、PlayerSettingの「API Compatibility.Level」を「.NET 2.0」に変更して再ビルドすることで何とか解決?しました。

投稿と設定まで完了したのは19時前頃です。余裕持って完成できるかと思いきや、最終的には結構ギリギリになってしまいました。

感想と反省点

「1週間でゲームとしてまとめあげる」ことは、仕事の「決められた期日内で物を納める」こととほとんど同じです。
本ブログでもいつも良いものを目指しすぎるばかりに作業が頓挫することが多いので、今回のゲームジャムは「妥協するところは妥協して、譲れないところはしっかり作る」という良い練習になりました。
曲がりなりにもゲームとしての体裁を保ったものをアップすることができたので、「期限内にやりきる」という意味ではクリアできたかと思います。
総じてすごく良い経験になったので、今後もチャンスがあれば参加していく予定です。

反省点として一番引っ掛かったのはWebGL上で実行した際の処理落ちです。
WebGLで実行させることを考慮せずに作り進めた結果、結果的に処理落ち対策で3回もリファクタリングをすることになってしまいました。Unityエディタ上だけでなく、定期的に対象プラットフォーム上で動作確認をすることの大切さを痛感した次第です。

あと他の方々の作品と比べて感じたのは「デザインセンス」ですね。
バックのC#スクリプトを書くのは(数学的な計算以外は)得意な方なのですが、表側のUIデザインやロゴ、ステージ・オブジェクトのモデルやテクスチャはあまり褒められたものではありません。
一部テクスチャはアセットストアから取ってきているので確実ですが、それ故に自前で用意したものとの差が気になります。
「Webデザインが出来るようになりたい」という意味でも、各種グラフィックソフトやデザインの勉強を行っていきたいところです。

使用した仕組み

ゲーム制作時に本ブログで紹介した仕組みをいくつか使っているので、ここでその一部を紹介します。

OnTriggerEnter()での衝突位置の取得
鉄の箱を叩いたときに吹き飛ばすベクトルの算出で使用しています。

【Unity】物理演算を(なるべく)行わずにオブジェクトの衝突位置を取得する方法

・木箱をバラバラにする
今回作ったゲームの場合、これがないとゲームの見た目がかなり地味になるため、結構重要な要素です。

【Unity】破壊時にバラバラになる木箱の作成

・カメラのフェードイン/フェードアウト

【Unity】シーン遷移時のカメラのフェードイン・アウト処理の実装

その他、プレイヤーの移動や攻撃の実装は「アザラシを守るゲーム」をベースにしている部分が多いので、そちらの記事やゲームも参考にしてみてください。

down

コメントする