「Burning Snowman」が出来上がるまでの話
概要
雪だるまが松明を持って、町を温めて行くゲームを作りました。
オーソドックスな2dになりそうだ。。寝ます #unity1week pic.twitter.com/HDAtxSAsB7
— ☕りょう (@plus_marumaru) September 7, 2018
Burning Snowman | 無料ゲーム投稿サイト unityroom - Unityのゲームをアップロードして公開しよう
あらゆるアクションでヒットポイントが減っていくハードなアクションです。 アクションごとにヒットポイントの減る量は異なります。減りの少なさに応じて、プレイヤーのスキルを要求します。
完全敗北した話も書いてます。よかったらこちらもどうぞ。
こちらの記事では、
どのような流れで企画が立ったか、実装面で工夫したところなどつらつら書き残しておきます。
- 2人で開発(相手はunity未経験、ゲーム開発未経験)
- 筆者フル稼働(毎日14時間、total90時間くらい思考&作業)
企画の話
メンバー全員でブレストして、両者いいねってなったものを採用することにしました。
頭の中にあるものを吐き出す
構図があまりわかなかったのでNG
オンライン対戦は、条件が同じプレイヤー出ないと、調整がしんどそう
みんながわかるもの
シンプルすぎるからもう少し駆け引き的なものが欲しいとのことでぼつ
ジレンマが起きる構造を元に思考
暑さでダメージを受けるキャラがいいということで思考した結果、ゆきだるまに行き着く。
- 雪だるまが松明を使って、世界を救うアクションorアドベンチャー
- 松明を使えば、世界を暖かくできるが暑さで自身も溶けていく
- あついがテーマなのに、まさか雪国をステージにする開発者いないよねってなって、目立つかなって思った
- キャラ設定とジレンマによって平和と悲しさがある壮大なストーリーを成立させることもできそうだ
プログラムの話
実装方針
- クラス名は、何をするかを明確にしておき、クラス名に関係のない(または薄い)挙動は別のクラスで実装
- uGUI周りはMV(R)Pのアーキテクチャで実装(UniRx使って)
- コンポーネントやゲームオブジェクトの参照について、インスペクターからさせないように努力(今回は使い方覚える体でZenject)
- インスペクターから変更できるパラメタはHeaderアトリビュート必須 パラメタ調整を分業できるように
設計については、過去2Dプラットフォームのゲームを作ってた経験から
なんとなくこういう作りにしておけばいいかなっていう当たりがついていたので、特にクラス図などは書きませんでした。
クラス名明確に付けることを心がけたことで、「あの挙動変更したいな〜」とか思ったらどこ変えればいいかの当たりがすぐに付きました。
例えば、プレイヤーオブジェクトについているコンポーネントはこんな感じです。
移動の挙動を調整したかったらPlayerMoverを見るとか。
Zenjectは使う必要が薄いというか、参照だけ取るのが目的だったら別の実装でよかったかな、と思ってます。
システムを動かす前提条件を差し替えるのを容易にしてくれるのを手伝ってくれる認識ですが、interfaceとか全く切らずに作ってたので全く使いこなせてなかったです。
最適化
そこそこできた段階でそんなに問題になっていなかったのですが、PCのスペックとかで重たかったりするのかなーとか考え、
少しでも快適に遊んでもらえるようにちょっとだけ入れました。
ほとんど効果ないかも。。
- 文字列連結周り(FastStringで対応)
- 敵の攻撃弾オブジェクトの使い回し(UniRxのPoolingで対応)
- コルーチンのyield returnで毎回newしているのは消してGCAllocate抑える
UIの話
ボタンとツールチップ
Modern UI PackというAssetが見栄えの点で優秀だったので使用させていただきました。
ボタンやツールチップはほぼこちらのアセットです。
(エディタ拡張とかがうまく動かなく動作が怪しいので、商用とかには使いにくいかも)
操作できるUIは、マウスオーバーしたらSEを鳴らすようにしています。
操作できますよ、という合図がわりです。
選択肢が複数ある場面では、ボタンに必ずツールチップを付けるようにしました。
説明の補足っていう意味合いもあるんですが、実のところは「今どの項目を選択しているか」をプレイヤーに理解いただくのが目的です。
ツールチップなし⬇︎
ツールチップあり⬇︎
背景ぼかし(Brur)について
モーダルウィンドウを出した際ウィンドウを集中して見て欲しかったので背景をぼかすようにしました。
ヒットポイントゲージについて
ピンチ感を煽るのが狙いで、被弾していくごとに青色→赤色にアニメーションするようにしました。
それから、ステージの設計と相談して配置位置は画面下にしてます。
イラストとアニメーションの話
メンバー全員が描けない。。。ってなって、いらすとやさんのものを使わせていただきました。
今回はこちらの面で失敗しました。
SNSでの拡散やサムネのことを考えると、ここは力を抜いてはいけない箇所でした。
サウンドの話
「自作するのもいいけど、他に優先することあるよね」ってなって後回しになった結果
各素材サイトの作品を使わせていただくことになりました。
それぞれのSceneではサウンドを変更し、場面転換したことを音で伝えるようにしておきました。
その他
空気感の表現
背景の山は遠くにあるものと近くにあるものでスクロール量に変化を持たせ、空気感を与えました。
また、雪のパーティクルについては遠くにあるものほど落下速度をゆっくりに・色を白に近づけるようにしました。
松明で明るくなっているプレイヤーを表現するため、ポストプロセスを使って画面四隅を暗くしてます。
会話シーンスキップ
周回プレイをして高スコア目指す人いるよねって話になって、会話スキップ入れたいという話が出ました。
当初ボタンで済ませようかな〜って考えていたのですが、物語見たかったけどマウスクリックしてたら勝手にスキップしたとか、 じゃあ確認画面挟むかってなっても操作1回増えるので、ボタン以外の方法で実装しました。
会話シーンでマウスやスペースキー長押しでスキップできるようにしてます。
オクトパストラベラー(と、あとツイッターで誰かがつぶやいていたゲームがあったけど、、思い出せない) で使われている手法です。
物語楽しみたい人、スキップしたい人の折衷が取れていると思います。これ考えた人ほんとに天才。。。
ゴール地点を見せる
オーソドックスな2dになりそうだ。。寝ます #unity1week pic.twitter.com/HDAtxSAsB7
— ☕りょう (@plus_marumaru) September 7, 2018
ここまでたどり着けばゴールですよ、というのを伝えるのを狙いとして取り入れました。
これがないと、どこまで進めば良いのかわからない。
※Hollow Knightのようにあえてゴールを見せずに、不安感を煽るアイデアもあるので、全てに当てはまるわけじゃない。
伝える情報を順に出す
聖徳太子のような、複数の情報をまとめて出して回答させるの、疲れちゃうかなと思ったので
できるところは小分けにして順々に伝えるのを意識しました。
例えばクリア画面の例⬇︎
「遊び方わからない→離脱」を避ける
キーボードどれ押せばいいの?とかが分からずに、過ぎ去られるのが嫌だったので色々気を使いました。
起動直後の初めの会話シーンは、マウスクリックのアイコンで進めますよアピールをしてます。
初めの会話シーンが終わった後のタイトル画面では、日本語で何を押せば進めるのか記載しておきました。
これについては、青木ととさんが作られたゲームのUIを参考にしてます。
青木ととさんのゲームはこちら⬇︎
Out of a Hole | 無料ゲーム投稿サイト unityroom - Unityのゲームをアップロードして公開しよう
それから、チュートリアルステージを用意しました。
理想を入れば、こんなテキストで説明したくない(テキスト読んで理解するのめんどくさい、マリオのように理解させたい)のですが、
キーボード使う関係上入れておきました。
こちらでも、伝える情報を順に出すのを意識してます。
チュートリアルステージでは敵がすでに配置されているのですが、
「このオブジェクトは敵だ」というのを認識してもらうためにわざと被弾する配置に組んでます。
初見では多分敵と認識できてないはず、なので被弾します。
被弾を繰り返すと、下部のゲージが減少し警告色になるようにしてます。この流れで、「こいつと接触したらいけないんだな、ジャンプで回避しよう」という思考に持っていき、ジャンプの使い道を覚えてもらいます。
少し進んだ先では、ジャンプでは乗り越えられない敵を用意しておいてます。
こういう場面では、松明を使うことで敵を溶かし先に進めることを覚えてもらいます。
各アクションにはダメージ差があるのですが、遊び方の説明で多分きちんとできてなかったです。
ジャンプでは低ダメージ、松明では中ダメージ、それから敵の被弾は大ダメージで組んでます。
ジャンプはhigh risk / low use、松明はlow risk/ high use の関係としてアクションの取捨をしてもらいたかったのですが。。
申し訳程度に、HPが減った時にキャラの上部にダメージ数をテキスト表示させ、ダメージ数に比例してテキストを大きくするのを入れておきました。
ポーズの一工夫
再開するボタンを押したらすぐ始まるのではなく、一呼吸置いてから始まるようにしています。
画面の状態をinputしてもらって、次のアクションどうしようかなっていうのを考える余地を与えるのが狙いです。
これは音ゲーとかのポーズを参考にしました。
※ポーズしても敵が動くというバグがあったため、あんまり役に立たなかったかも。。
離脱ポイントの記録
テラセネを作られている方のブログを見て、ファネル分析たる存在を知り良さそうだったので、1weekでも取り入れてみました。
テラセネって何?って方はこちら⬇︎
今回作ったゲームでは、いくつかチェックポイントが用意されてます。
チェックポイントを通過したらサーバーにリクエストをかけ、プレイヤーの行動ログを記録しておきます。
- 特定シーン読み込み時
- 特定オブジェクト接触時
記録しているデータはこんな感じです。
これを見ることで、「〇〇さん、STAGE_Cのログを最後に記録がない。。つまらなくて途中で去ったんだな。。」とかが分かるようになってます。
用途については、
今回のゲームジャムの振り返りをするのに使ったり、月曜日から遊んでくださる方向けにゲームバランス調整するのに使いました。
日曜は疲れてて月曜から遊ぶ!っていう人いるって信じてる。
ニフクラさんのサービスが優秀で、実装も楽でした。(今見たらenum.tostring使っちまってる。。)
public void RequestRecording (EnumCheckPoint checkPoint){ #if UNITY_EDITOR Debug.Log("チェックポイント" + checkPoint.ToString() + "を記録しました。"); return; #endif try{ // クラスのNCMBObjectを作成 NCMBObject historyClass = new NCMBObject("HistoryData"); // オブジェクトに値を設定 historyClass["playerId"] = playerId; historyClass["checkPoint"] = checkPoint.ToString(); // データストアへの登録 historyClass.SaveAsync(); }catch(System.Exception ex){ Debug.LogError(ex.Message); } }
次回も使えるまとめ
- 企画については対立がおきたりジレンマが発生する構造から先に考えるとうまくいく
- 会話場面でのスキップ機能は長押しでやるのが良案
- プレイヤー行動ログを残しておくと色々と次に活かしやすい