Unityでゲームを作る時に意識しているコードの書き方

# 概要
半年前、Unity1週間ゲームジャムに個人で参加し、そこで私はふしぎなポケットというゲームを制作しました。
(私が作ったゲームのURL:https://unityroom.com/games/mysteriouspocketcookies)
その際(というかいつも)Unityでコードを書く際に気を付けていることをまとめたいと思います。

# Unity1週間ゲームジャムとは

Unity1週間ゲームジャムとは、一言で言うとnaichiさんにて主催されているゲームのハッカソンです。
(Unity1週間ゲームジャムのURL: https://unityroom.com/unity1weeks)
月曜日の0時にお題が発表され、そのお題に合わせたゲームを１週間制作していきます。
制作期間が終わるとゲーム評価期間になり、その期間でお互いにゲームをプレイし評価していきます。

また、このUnityゲームジャムが終わった後に参加した人たちで勉強会も開かれています。
(アーカイブのURL(1回目):https://www.youtube.com/watch?v=rao90BS-OX8&feature=youtu.be
　　　　　　　　 (2回目)https://www.youtube.com/watch?v=SS_2VbdzSL0&feature=youtu.be)

ちょうど明日の2020/12/21(月)からはじまります。
気になった人は参加してみてください。


# コードを書く際に気をつけていること

私は、以下の3つのことに気をつけながらゲームを制作しています。

1.　変数の変更しやすさ 
2.　他の人がみてもわかりやすい
3.　同じことを繰り返さない

詳しい話はのちにしていきます。

# 1.　変数の変更しやすさ 

ゲームはレベルデザインのために変数などを変更することが多いです。
そのため、「変数の変更しやすさ」はかなり重要なことだと私は思っています。


ふしぎなポケットでは、変数だけのクラスを作り、その変数を変更するだけでゲームに反映されるようにしています。

実際にどのようにコードをかいたのかは以下の通りです。

```C#

// 変数をまとめて保持するクラス
public static class GameInfo{

        // クッキーを作成する総数
        public static readonly float COOKIE_NUM = 30;

        //　クッキーの大きさの範囲
        public static readonly float MIN_COOKIE_SCALE = 1.0f;
        public static readonly float MAX_COOKIE_SCALE = 2.0f;

        //　ゲームの時間
        public static readonly float GAME_TIME = 30;

        //円のスピードの最小値、最大値
        public static readonly float MIN_SPEED = 0.01f;
        public static readonly float MAX_SPEED = 0.05f;

        public static readonly float MAX_CSIZE = 1.5f;
    }

```

例えば、このクラスにあるゲームの時間を保持するGAME_TIMEを値を変化するだけで、ゲーム全体の時間を変更することができます。

# 2. 他の人がみてもわかりやすい

私が最初にUnityでゲームを作った際、ゲームの状況管理やイベント発生などをlabelという変数を作り、それぞれで管理していました。

しかしそのようなやり方だと、変数の数が増え、コードが読みづらくなってしまいます。

そこで私は、enumを使用し文字化する事で直感的にわかりやすくしています。

``` C#
    //ゲームの状況を管理する
    public enum GameState{
        COUNT,
        MAIN,
        GAMEOVER
    }
```

上のenumから直感的にゲームの状態が分かりやすくなっていると思います。

``` C#
　　if(currentGameState == GameState.MAIN){
　　　　　//ゲームが始まっている時の処理
　　}
　　else if (currentGameState == GameState.GAMEOVER){
        //ゲームが終わった時の処理
　　}
　　else if(currentGameState == GameState.COUNT){
        //ゲームが始まる前の処理
　　}
```

処理を書く際も、上のように書けばいいのですごく分かりやすいです。

ちなみに、elseを使うとどの処理なのか明記されておらず分かりづらいので、
if,else ifを使い毎回どんな時の処理なのかを書くようにしています。

# 3.　同じことを繰り返さない

同じような処理をするときは、関数化をすることで無駄な処理を減らしていきました。

また関数化をしていけば、バグがあった時どこをみればいいのかを関数名から推測することも可能です。
試しに、関数化して書いたものと関数化せずに書いたものを比較したいと思います。

``` C#
// 関数化したもの
if(currentGameState == GameState.MAIN){
            CookiesControll();
            GameTimeCounter();
            ScoreText.text = "てもち"+((int)ScoreManager.instance.score).ToString() + "枚";
            ChangeBackground();
        }

```

``` C#
// 関数化せずにだらだらとかいてしまったもの
if(currentGameState == GameState.MAIN){
          if(DisplayIndent < GameInfo.COOKIE_NUM){
            float rtime = TimeCounter(GameTimes);
            float time = GameInfo.GAME_TIME - rtime;
            float stime = Cookies[DisplayIndent].GetComponent<cookie>().Getstime();
            
            if(time > DisplayIndent + stime){
              Cookies[DisplayIndent].SetActive(true);
              DisplayIndent++;
            }
        　}

         for (int i=0; i < DisplayIndent; i++){

            if(Cookies[i].activeSelf){
                GameObject circle = Cookies[i].transform.Find("circle").gameObject;
                float speed = Cookies[i].GetComponent<cookie>().GetSpeed();
                circle.transform.localScale += new Vector3 (speed,speed,1); 

                if (circle.transform.localScale.x > GameInfo.MAX_CSIZE){
                    Cookies[i].SetActive(false);
                }
            }
        }
        //時間をカウントする
        GameTimes = TimeCounter(GameTimes);

        //時間を表示する
        timeText.text = "あと"+((int)GameTimes).ToString() + "秒";

        //3秒前の音
        if( 0 < GameTimes && GameTimes < 4){
            if ((int)GameTimes <= count3 && count3 < (int)GameTimes+1){
                AudioManager.Instance.PlaySE("count");
                count3--;
            }
        }

        if(GameTimes < 0) SetcurrentGameState(GameState.GAMEOVER);
            ScoreText.text = "てもち"+((int)ScoreManager.instance.score).ToString() + "枚";
        if(((int)ScoreManager.instance.score-GameInfo.COOKIE_NUM )%20 == 0) {
                int index = (int)(((int)ScoreManager.instance.score-GameInfo.COOKIE_NUM )/20)-1;
                if( 0 <= index  &&index < 4){
                    CookiesBackground.transform.GetChild(index).gameObject.SetActive(true);
                }
            }
        }


```

関数化してないコードを見ると、バグを探すことやリファクタリングしたくないですよね。


# まとめ

今回は、私がUnityでゲーム制作する際に気をつけていることをまとめました。
ぜひ、このゲームのコードは公開しているので、みていただけると幸いです。
(GitHub:https://github.com/kurobei0314/break_cookies)

今度のゲームジャムでは作るだけではなく、面白さまで追求できるようにしたいと考えています。