グループでの制作を完遂するために役に立つ(かもしれない)ノウハウをまとめます。
<aside> 🤝
これはオンラインでも実際に合うのでも良いのですが、部会以外でグループのみんなが集まる日があると、いいことがたくさんあります。
一週間に30分とかでもいいので集まりましょう。 …どうせ30分じゃ満足できなくなって1,2,3,4時間くらいずっと話すようになりますよきっと。
</aside>
<aside> ⚙
ゲームを作るならまずは最低限の動きだけをするプレイヤーと最低限のステージを作ります。それで動くのを確認してから機能やステージを追加していくべきです。細かいところにこだわるのはその更に後です。
</aside>
<aside> 📕
ゲーム開発あるあるとして、なぜかアセットを使わないことにこだわってすべて自作しようとすることがありますが、これは非常に大変です。アセットだけを使うゲームというのはそれはそれで味気ないものの、細かいところまで自作していてはあまりにも手が足りません。世の中には多くのすばらしい無料アセットや素材があります。これを活用することで効率的にゲームの品質を向上させることができます。
</aside>
<aside> 🤔
Unityはかなり老舗のゲームエンジンですから、みなさんがやりたいと思う大抵のことをそれなりに簡単に実現する手立てを持ち合わせています。すべてをプログラミングで解決することも不可能ではありませんが、Unityに便利な機能があることを知っていれば一発だった…なんてことはよくあります。「これだけのことするのにこんなに大変なのおかしくね?」と思ったら調べるなり質問するなりしてみましょう。
</aside>
<aside> 🉐
学生ならなんと無料で使えます。コードを書いている途中勝手に「こういうことがしたいんじゃないの?」って察してくれてTabキーを押すだけでそれを完遂してくれます。プログラミングだけでなく、テキストエディタを使うあらゆる作業が効率的になります。(私も謁見のときなど大変助けられました。)使用にはGitHubに学生である証明を送る必要があり少々面倒ですがその価値は十二分にあります。(もちろん、AIに頼りすぎて自分の力が育つ妨げにならないように注意して使いましょう。)
登録方法はこちらのサイトに詳しく載ってます。
</aside>
<aside> 📏
ファイルの名前やコードの書式を揃えることで他のグループメンバーが理解しやすいようにしましょう。グループで書式を統一しておくと後からデバッグなどで見返すときに非常に楽です。
コードでは適宜コメントで適切な注釈を加えることも有効です。
また、当然ですができるだけ簡単なロジックのプログラムになるように設計しましょう。
以下は慣習的によく使われているルール(お作法)の例です。
クラス名や構造体名、メソッド名などの「ゲーム中変化しないもの」はパスカルケース(先頭大文字、単語区切りも大文字)
public class PlayerController
public struct EnemyData
public void MoveToTarget()
public int GetHealth()
変数名はキャメルケース(先頭小文字、単語区切りは大文字)、定数名はすべて大文字で単語区切りはアンダーバー
private int currentHealth;
float speed;
public const float MAX_HEALTH = 100f;
インデントはスペース4つ分にする
VSCode右下の「スペース:なんちゃら」の部分をクリックし、「スペースによるインデント」から変更可能です。既定(デフォルト)のタブサイズを変更するにはCtrl+, から開く設定で「Tab size」の値を変更すればよいです。
波括弧開きは改行せず、波括弧閉じは改行する。(波括弧開きを改行する流派もあります。)
if (isDead) {
Respawn();
}
独自の(一般的でない)略語はなるべく避ける
適切にコメントを残す(大事) 。自分が行った実装の意図が伝わるように書きましょう。
// プレイヤーのHPを初期化する
private void InitHealth() {
currentHealth = MAX_HEALTH;
}
複雑な処理は別の関数にして分解する
例えば「自分と相手の距離と攻撃力と防御力と相性から与えるダメージを決定する」などの処理のための場合分けをそのまま直に書くのは推奨されません。float Calculate Damage (distance, attack, defense, compatibility)
のような別の関数を用意しましょう。
同じ処理を何度も書かない
例えば「敵Aに当たったときHPを1減らし無敵時間を付与する」「敵Bに当たったときHPを2減らし無敵時間を付与する」という処理を書くときに、if(敵Aに当たった)
とif(敵Bに当たった)
の中にそれぞれ直接、計2回同じ処理を書いてしまうと、変更するときに2箇所変更しなければならないため非効率的でミスの元にもなります。「HPをx減らし無敵時間を付与する」という関数を別で作って、その関数を呼び出す形で実装しましょう。
詳しくは部室にある「リーダブルコード」などの書籍を参考にするとよいでしょう。
また、詳しい人/興味がある人は.editrconfigなどを使ってコードスタイルを強制的に統一してみてもいいかもしれません。
</aside>
<aside> 📂
同じファイルに対して同時に複数の人が変更を加えると良くないことが起こるおそれがあります。(詳しくはコンフリクトで検索。)この対策として有効なのがファイル整理です。作ろうとしているゲームの設計にもよりますが、主に以下の2つの整理方法が考えられます。
方法A: 作者で区分
<aside>
Assets ├Tanaka │ ├illust_A │ ├illust_B │ ├illust_C │ ├illust_D │ ├illust_E │ └code_A ├Yamada │ ├music_A │ ├music_B │ ├music_C │ ├sound_A │ └sound_B ├Sato │ ├code_B │ ├code_C │ ├object_A │ ├object_B │ ├object_C │ └object_D └Takahashi ├code_D ├code_E ├code_F └code_G
</aside>
メリット: 誰がどのファイルを作ったか一発で分かるのでコンフリクトが起こりにくい。
デメリット: どのファイルがどこにあるか分かりづらい。システムの中枢など複数人で作る大きなファイルの分類に困る。
方法B: 種類で区分
<aside>
Assets ├Code │ ├code_A │ ├code_B │ ├code_C │ ├code_D │ ├code_E │ ├code_F │ └code_G ├picture │ ├illust_A │ ├illust_B │ ├illust_C │ ├illust_D │ ├illust_E ├sound │ ├music_A │ ├music_B │ ├music_C │ ├sound_A │ └sound_B └src ├object_A ├object_B ├object_C └object_D
</aside>
メリット: どこにどの種類のファイルがあるか分かりやすく、分類も容易。
デメリット: ファイルの作者がわからないのでミスがあったときの連絡やコンフリクトの対策が困難。
ちなみに去年の私が所属していたグループではこのハイブリッドとしてファイルの配置は方法Bを使いつつ、ファイル名の先頭に作者が分かる記号(イニシャルなど)をつけるようにしていました。また、一部のファイルはスプレッドシートに関連情報を残すようにしていました。
</aside>
$$ \tiny\color{#888888} なんで去年のグループ制作チャンネル消しちゃったんですかね。今年度は絶対に消させません。 $$