見出し画像

unityでタワーディフェンスっぽいのを作ったので振り返りメモ1

https://unityroom.com/games/syusakutowerdiffence
unityとC#の勉強の一環でタワーディフェンスの習作みたいなのを作って公開できたので、得られた知見など色々振り返っていく。

まず断っておくこととして、自分は独学でunityとC#を学んでおり、やり方や考え方、何よりつまずく場所とつまづき方の正しささえ知らない身の上なので、本職やちゃんとした頭脳の持ち主が見たら吐き気を催す記事になるかもしれない。その点ご承知いただいたうえで、もしあなたにスーパーエンジニアとしての技術と知見、そして慈悲の心があれば、改善点をコメント等でご教示いただきたく思う。

制作にあたって

当方、ブロック崩しやじゃんけんゲームなどの単純なものは作ったことがあったくらいで、タワーディフェンスというちゃんとしたシステムのゲームを作るのは初だったが、手を動かしてみればifとforとListでゴリ押しができる「あの感覚」がここにもあったため、完成はできるだろうなという見込みのまま続行し、制作を行った。プログラムの部分だけで言えば23年の10月頭~24年の1月いっぱいくらいで完成し、基本形だけは3ヶ月くらいで作れたような覚えがある。

ただ、ゴリ押しコーディングは前に作ったブロック崩し(開発期間1ヶ月程度だったような気がする)でさえあとから見返したときにうんこを漏らしそうなほど後悔した覚えがあり、そういったことを防ぐために以下の点を意識して取り組んだ。

  • 読みやすいコード

  • 制作で楽ができる仕組み

  • 今まで使ったことのない、C#かunityの機能の利用(こっちはただの挑戦)

結果、コーディングはまさしく竜頭蛇尾のごとくなってしまったのだが(多分ルーリングがそもそもよくわかっていないのだと思う)、その他に関しては及第点と言っていいように思う。

しかし上記とは別に、完成させて初めて浮き彫りになった課題の存在も大きくある。それも含めて、できたことやできなかったことを以下でざっと触れていきたい。

「読みやすいコード」←これ

英語がわからないのに英語でわかりやすいコードを書けって普通にとんちとかのレベルだと思う。
エンジニア諸兄は破綻した文脈に意味を見出してしまう悲しい生き物だとは思うのですが、一般人の目線に立ってみて上の一文読んでみてほしい。意味わからなくないですか?https://www.amazon.co.jp/%E3%83%AA%E3%83%BC%E3%83%80%E3%83%96%E3%83%AB%E3%82%B3%E3%83%BC%E3%83%89-%E2%80%95%E3%82%88%E3%82%8A%E8%89%AF%E3%81%84%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E6%9B%B8%E3%81%8F%E3%81%9F%E3%82%81%E3%81%AE%E3%82%B7%E3%83%B3%E3%83%97%E3%83%AB%E3%81%A7%E5%AE%9F%E8%B7%B5%E7%9A%84%E3%81%AA%E3%83%86%E3%82%AF%E3%83%8B%E3%83%83%E3%82%AF-Theory-practice-Boswell/dp/4873115655

変数やメソッド名を記述するのには英語を用いるわけですが、英検3級マンにパッと思いつく英語には限りがあるので、まあ調べるわけですね。
そうすると同じ意味で2つ単語が出てくるので(やめろ)、文脈の違いを調べて、みたいなことやるんですが、これたかだかインターネットの検索結果でTOP3のページが言ってること鵜呑みにして名付ける方が危険だったりしないんですかね?ネイティブ横にいる状態で聞いたりしない限り無理じゃないですか???

なので、日本語のローマ字記述とか頭文字の大小とかでお茶を濁していくうちに自然と地獄が完成していった。
先に述べた竜頭蛇尾ってのもこれで、きれいなコードを書くために英単語を調べるとかで時間を使っていたもののあまり意味をなしているように思えず、結局名付けに関してはメチャクチャな部分ができてしまった。
唯一はっきり覚えているのは、ifの条件分岐内での記述をローカル変数に入れてスッキリさせるやり方で、クソでかい恩恵を感じたように思う。

この辺はおそらく「わかりやすい英語力」ってよりも「わかりやすい名付けのルール」を決めておく日本語の構成力がまず試されているような気がする。
「プログラミングで最も必要な言語は母語」の一端だと思うが、どうだろう。ルーリングに焦点を絞ってる良い教材とかあったら教えてほしいです。

制作で楽ができる仕組み

タワーディフェンスを作るにあたって、画面構成やジャンルならではのお約束、基本形といったものを整理するところから始まり、どこを作り込むかではなく割り切って作るかをはじめに形にしたのが非常に役立った。
「楽ができる仕組み」というのも、その仕様決めの段階で漠然と意識したことであり、それはタワーディフェンスがステージクリア型のゲームであることに由来する。
要は、ひとつひとつのステージは違っていても使うユニットやシステム自体が同じであれば、雛形を作って量産できるはずだという考えがあった。

具体的には、C#の機能では継承を用いて、unityの機能ではSceneTemplate(シーンテンプレート)を用いた。
継承は入門書を買えば書いてある類のもので、概念としての解説はより優れた書籍やページがあるのでそちらを参照していただくとして、後者の方は名前の通り、unity上で作成するSceneのテンプレート(雛形)を登録しておいて、あとから同じものを量産できるという機能のこと(だよね…?)。
プレハブなどのリソース類もコピーを作成するか雛形で使われているものと同じものを使うか、シーンを登録する際に細かく設定できるので、雛形と同じものにしておけばおおもとのプレハブの設定をいじればすべてのシーンで同じ設定が反映される…というか同じ素材を使っているのでシーンごとに個別に調整する必要がない。逆にコピーを作成するのは、例えば演出用に外見は同じだけど内部の値が違う何かを用意する必要があったりするときなどだろうか。

まあ自分は全部コピーで作成しちゃったせいでいちいち個別に調整したんですけどねハハッ。

継承について

タワーディフェンス作成に当たり、自ユニットは最低3種類作成する、ということをはじめに決めていた。
結果としてアタッカー(STRIKER)、サポーター(JUMMER)、あとなんか面白いの(BELLMAN)を作ったが、ロールが違えど敵の検知やリストへの格納、必要な変数など処理の土台の部分はほぼ同じであることは予想できたため、そこを共通化してユニットの個性の部分だけあとづけして無限に新実装できるようにした。

継承の利点としては、親クラスはともかくとしてコードがめちゃくちゃにスッキリすること。
親の時点で動作が保証されていればエラーが起きたときに子の差分処理だけ見ればよいというのも嬉しいし、そのためにカーソルをあっちこっち移動させなくていい、目玉だけ上下させれば間に合うというのが本当に楽だった。

また、親クラスでのメインループの回し方を工夫する必要があるが、全体の処理の流れが明確になるのも利点であり、ユニットそれぞれが好き勝手なタイミングで処理をしないことが保証できるのもいいと思った。
ユニットすべてが独自のアビリティを持っているとしても、内部の処理を見れば、
敵の検知→値を格納→攻撃→ユニークアビリティ→相手から受けた処理→繰り返し…
の流れがすべてのユニットで保証できるという前提があれば、仕様を決める際に非常にスムーズにいく場面が多いように思うし、起きるバグの検知もしやすくなるように思う。
なんかunity触りたての頃にも同じこと思ったけど、TCGのフェーズ処理そのまんまだなって思いながらやってる。

以下、余談。

聞くところによると継承よりもインターフェースを使うべきだとかいう意見などがあるらしく、よくわからないので言われてるんならとそれに習おうとしたのだが、インターフェースの利点として機能を細かく分けることでより柔軟に使用できる点がある…らしい。

若干だけ触ってみたのだが、結果としては習作としてのゲームに使用するという点と、共通の処理を持つ複数種類のユニットを実装する目的では細かけ分けるほうが複雑で面倒な気がしたので、使用しないことにした。
自分のプログラマレベルが低く、とにかく手を動かしてみて判明することが多い段階にあるので、結論ありきで先に分けておく、みたいな処理は合わないのだと思う。

思ったより長くなりそうなので

もうちょっと書きたいことあるので記事分けます。
もうちっとだけ続くんじゃ。

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