見出し画像

Unity1week備忘録(ナット)


初めまして、ナットと申します。
ゲーム制作サークル「平安京スパナ」でプログラマをやっています。

今回は先日、サークルとして(私個人としても)初めて公開した「M87」の制作過程を備忘録としてここに記していこうと思います。

画像2

私は絵を描くなどのグラフィック関係は全く分からないので、雰囲気作りの仕方などは同じアカウントから投稿されている共同制作者のsatsukiさんの記事に任せようと思います。

まず、私はUnity超初心者です。この記事においてあるコードなどもゴミみたいなコードですので、もし参考にされる方がいらっしゃるならご注意ください。質問などございましたらtwitter等に連絡くだされば答えられることは答えたいと思います。

私がこのM87の作成を始めたきっかけはunityroomでの第15回Unity1week「密」の告知を拝見したためです。
もともと平安京スパナとして別のゲームを制作していたのですが、簡単なものでも一つ完成品を世の中に出すことが遠回りにはなっても今作成しているゲームのためにもなると考え、平安京スパナとしての参加を決意しました。



ゲーム制作の流れ


まずはSatsuKiさんとお題の密から連想ゲームをしました。
結果、「蜜」「三つ」「密度」「密密(ひそひそ)」「密接」あたりがゲームにしやすそうかなという印象を受けましたが、結局その場ではどうするか決まらず持ち帰り検討することに。

SatsuKiさんの「自分より密度の低いものには触れられる」という言葉がきっかけで頭の中にほぼほぼ今と同じシステムが思い浮かび、丸と四角だけで頭の中を非常に簡単にアウトプットしSatsuKiさんとイメージの共有を図りました。
百聞は一見に如かずとはよく言ったもので、簡単なものでも一度アウトプットするとイメージの共有が恐ろしく早いと痛感しましたね。
ただし、このころにはまだ自分の密度に関係なく密度を上下させるオブジェクトは採用するつもりはありませんでした。

その後、各オブジェクトのスクリプトを完成させてからステージ制作に入ったのですが、パズルゲームの作成難易度をなめていました。あっちを立たせればこっちがたたず、こっちを立たせればあっちがたたずな感じでさすがこれは無理だと投げ出した結果「私たちの救済措置」として密度上昇ブロックと下降ブロックを追加しました。
基本的にはすべての画像素材はSatsuKiさんに作っていただきました。アニメーションも差分をすべて出力してもらったのでSatsuKiさんの作業量やべぇな…神かな?

ステージの内容は私が4つ、SatsuKiさんが5つを考えました。
平安京スパナでUnityを扱えるのは私だけなのでSatsuKiさんからは以下の画像のような形で納品していただきそれを私が改めてUnity上で配置するといった工程をふみました。

画像2


ステージ作成の工程がやはり一番時間がかかったのですが、ステージギミックを考えることよりもステージにブロックを並べる作業がもっとも時間を要しましたね
今考えるとプレハブをドラッグして並べるだけの作業だったため、SatsuKiさんのPCにも作業環境を整えてここだけでも手伝ってもらったほうがよかったかもしれないです。(最終的にSatsuKiさんをだいぶ待たせてしまいした…)
百合子ちゃんはしばらく見たくないです。

ステージがそろったところでステージセレクト、スタート画面を作成したのですがここで「一応説明欄にも書くけどゲーム内にも操作方法が書いてあるほうがいいのでは?」ということになり新しくアソビカタを追加。このあたりでゲームの雰囲気がどのような感じになるのか私にも想像がつくようになりました。(遅い)

ちなみにBGMはこの辺りで選定しました。割とこのころには私の作業しか残っていなかったのでBGMの選定はSatsuKiさんにお願いという名の丸投げでしたね。やはりSatsuKiさんは神

その他細かい修正を行い、unityエディター上でテストプレイを行ってクリアチェックが済んだためwindows用にビルドして友人にテストプレイをお願いしました。この時は特に大きなバグも見つからず、軽微な修正で済んだのですが今考えるとテストプレイを一人にしかお願いしなかったのは問題だったかなと思っています。まあ、細かい反省はまた後で書くとして先に進みましょう。

最終確認も完了したところでwebGLにビルドしたのですがここで問題が発生。
unityroomのwebGL出力の方法も確認したのですがどうやら別の問題の模様…
いろいろ試してみた結果UnityEditer用のスクリプトが悪さをしていたようで、そのスクリプトを消したらうまくいきました。
この時は本当に焦りましたね…ゲームの内容に関係ないところで本当によかった。

後は公開するだけというところで画面の解像度の設定を間違えており、普段作っているゲームの1920*1080で作っていたのですがUnityroomでは960*540がちょうどいいという罠にかかり(初めに調べとけって話ですが)Canvas系のすべてのオブジェクトのパラメータとスクリプトを見直す羽目になりました…

公開後もたっくさんバグが見つかって幾度かアップデートを繰り返しました。

書いたスクリプト

スクリプト含めたunityのプロジェクトをgithubにアップロードしました。

ただ、人に見せる予定ではなかったプロジェクトで時間に追われていたため、コメントは皆無ですし変数名も自分さえわかればという理念で書いていて、挙句の果てには命名規則もガン無視して書いているのでひじょーに読みにくいかと思われます。なので簡単に解説(という名の覚書)を書いていきます。

GameManager

恥ずかしながら、GameManagerはどのように使えばいいものなのかわかっていません。なので私は基本的にいろんなスクリプトで共有する必要のある変数、関数ゲームプレイ中には発生しないインプットのみを記載しています。

具体的には各オブジェクトをStartで取得してなるべくプレイ中はGameObject.Findを使わないようにしています。まあ今回はほんとに焦ってたんで結構Findしちゃってますけども…。そのほかにそのステージでの最高密度の保存やクリアフラグの管理やそれに付随したシーンの遷移の管理などを行っています。

FixedUpdateではプレイヤーの移動を含まないインプットの管理をしています。ですので密度の表示もこちらのスクリプトで行っています。ゲーム中にいっぱい使うのでプレイヤーで書くか迷いましたが、あまりプレイヤーを重くしたくなかったのでこちらで書きました。今考えればそもそもインプットは別の一つのスクリプトで管理したほうがあとあと修正などしやすかったかなと思います。

Player

次のアップデートを考えてる段階でこの記事を書いているため、いったん保管しておくためのPlayer1.csが本編で実装されているスクリプトと同じ内容です。GetSPDもまだ使用されていないです。もしまたGitを更新することがあればのちのちこの記事も修正します…たぶん…。(Githubを使ったのはあくまでこのノートのためなので更新しない気もしますが…)

基本的には自分の色のrgbを(1-自分の密度/そのステージの最大密度)に設定することで色の変化をつけています。これはブロックでも同じシステムを採用しています。ですので理論上は255色くらいまでは色の差別を付けられます。今回白黒でステージを構成した最大の理由がこのスクリプトから色を簡単に変更できるのが白黒だったからという理由です。

こんな無茶苦茶な理由で決められたモノクロに対応してくれて雰囲気を作り上げてくれたSatsuKiさんには感謝。

ただ少し反省するならば、色の変更はFixedUpdateではなく、変更があった瞬間に呼び出す方式のほうが無駄に処理能力を使わなくて済んだかなということです。まあそんなに重い処理ではないし多少はね?

移動もこのスクリプトで書いています。基本は左右ボタンが押されたらRigidbody2Dに速度を与える、接地判定がtrueの状態でSpaceが押されたら上に速度を与えるという形です。接地判定は自分の足元のちょっと下に横幅プレイヤーの0.4倍くらいのRaycast2Dを飛ばしています。(ちなみに途中のアップデートでこの仕様に変更しましたがもとは自分の中心から自分の真下に飛ばすだけだったのでギリジャンが今よりも鬼難しかったです。)

今回の最大の反省点がこのプレイヤーの操作の仕様です。

慣性が強いゲームがあまり好きくないので慣性を付けなかったのはまあいいとして、ジャンプをあまりに適当に書きすぎました。時間がないにしても、ここは押している時間に対応してジャンプ力の変わるようなジャンプにすべきでした。(というかほかのゲームですでに作ってるんだからコピペして少し対応させるだけだろサボってんじゃねぇよ…)

そのせいで無駄にアクション要素の強いゲームになってしまったと思います。

それに、ゴール時の演出もキャンバスを出す以外はこちらで行っています。kouseiyouso(構成要素とかさすがにこのこの変数名何とかならんかったのか…)というGameObjectの子要素すべてにクリアしたよーという合図を送って、その後Stageブロックと接触したら自分のサイズを大きくなるようなフラグをオンにし、移動を不可能にしています。

また、吸収可能ブロックに触れた際に必要に応じて密度の変化を行うこともしています。

Goal、Block、Stage

わかりにくいですが、オブジェクトのBlockが吸収可能なオブジェクト、Stageが吸収できないオブジェクトです。
スクリプトのBlockはオブジェクトのBlockに張り付けるためのスクリプトなのですが、StageはBlock、Stageの親オブジェクトに張り付けるものです。

さらに、それぞれのオブジェクトは
kouseiyouso(空のオブジェクト)
⇒Stages(Stageコンポーネント)
⇒⇒Block(Block)、Stage(当たり判定とStageタグだけつけたオブジェクト)
というような親子関係になっています。

StageはタグとColliderを付けただけのオブジェクトです。

BlockはStageのタグを変え、Blockコンポーネントとsuutihyouziコンポーネント(シフト入力時に自分の密度が書いてあるCanvasをアクティブにするだけ)を張り付けています。

GoalはBlockにGoalコンポーネントを張り付けたものです。

Stageコンポーネントはクリアしたことをプレイヤーから受け取ると、子供のオブジェクトすべてに大きさ1のランダムな速度を与え、自分自身を回転させることで子のオブジェクトを回転させています。

BlockコンポーネントはPlayerの密度を参照し、自分より大きければ自分のColliderのIsTriggerをtrueにしています。

GoalコンポーネントはStartでGameManagerに自分の密度を伝えるためだけの存在です。

その他

その他のスクリプトは結構簡単に必要な機能を詰め込んだだけなので割愛します。

反省

もっとも反省しているのは操作性の悪さです。

ぱっと思いつくのはジャンプの挙動と左右移動に多少の慣性を付けるほうがいいのかなという感じです。
そして、Unity1weekの評価を見る感じ、難易度≒操作感というような形で評価に出やすいのかなというような印象を受けました。
今回はたくさんのゲームを一人が巡回してプレイするという特性上さらっとプレイせざるを得ず、その点このゲームではパズル難易度がそこそこ高いのにアクションでも緻密なプレイを要求してしまうという難点があり、それも含めて操作性、楽しさの評価が芳しくなかったのかなとおもいます。

今回操作性のランキングでトップだったゲームをプレイして思ったのは2Dアクションでは疾走感は楽しさということです。もうそれを言い出したらパズルアクションを選んだ時点で失敗なのでは?と思われるかもしれませんが、サクサク感というかもっとステージ数を増やして内容の密度を下げることで改善することができると思います。

次がチュートリアルが不親切だったという点です。これに関しては後から修正するかもしれませんが実際にプレイさせて理解させるべきだったと考えています。文字の情報だけでは人間案外しっかり読まないものだと理解しました。

次がスクリプトの構造です。機能を一つのスクリプトにまとめすぎたり、逆に分割しすぎたりした点が多く、修正するたびに無駄な変数が増えまくって今この記事を書きながら確認していてもこの変数いらんやん…ってなりまくってて恥ずかしい限りです。もっと初めにどのような構造にするかをきめてからスクリプトを作成するべきだなと感じました。

それでスクリプト構造の問題にも重なるのですが、もっとアセットに頼ってもいいのかなとおもいました。これまで「アセットとか他人が書いたものなんだからできるだけ使わないほうがよくね?」とか生意気なことを考えてアセットを毛嫌いしていた面があるのですが、よくよく考えたらアセット=自分にはできないことを非常に高水準で実現してくれる神アイテムなんだよね。私の座右の銘ともいえる最大の結果を最小の努力でにめっちゃ反することしてたなと反省してます。

あとは、SatsuKiさんに素材を要求するときにはもっと具体的に要求しなきゃなということです。これは前々から意識はしているのですが、語彙力がなくなかなか解決しません…どうしたらええねやろ。

最後に、テストプレイの不足です。プレイをお願いした人間がかなりゲーム慣れしている人間一人だったためこのゲームを投稿する前に操作の難易度が高いということを把握できなかった。もっと知り合い総当たりでテストプレイをお願いすべきでした。(友達いないんだけどどうしたらいいんだろうか)

他にもたくさんの反省点がありますが、すべて書いているとこの記事の投稿が10年くらい先になりそうなのでこの辺でやめておきます。

終わりに

こんな長くて読みにくい記事をここまで読んでくださった方がいらっしゃるならお住いの地域を教えてください。一生その方角に足を向けて寝ません。

Unity1weekでも112件という本当に多くの評価とコメントをいただきうれしい限りです。遊んでくださった皆様本当にありがとうございました!

仕事でプログラムを書いているというわけでもなく趣味で書いてきただけなのでスパゲティもびっくりするぐらい絡まったコードですが、どなたかのお役に立てたなら幸いです。
はじめにも書きましたが、質問等あったらコメントを下さるかTwitterにDMを送ってもらえれば回答します。

また、このアセット便利だよとかあったら教えてもらえると助かります。これまでアセット全く使ってこなかったからまずどんなものがあるのかすら知らないんですよね…

とりあえず、今も別のゲームを制作している真最中ですのでよければサークルのTwitterだけでもフォローしてもらえると嬉しいです。

重ね重ねにはなりますがここまで読んで下さって本当にありがとうございました!!


この記事が気に入ったらサポートをしてみませんか?