【Unity(C#)】ゲームオブジェクトを毎回違う場所に配置する方法

　　
　　
　　
この記事は

**『プログラミング完全未経験からUnityでの開発現場に迎え入れてもらえた世界一の幸せ者』**

の記事です。そのつもりでお読みください。 


##ランダムではない
**毎回違う場所に配置する**と書きましたが、
ランダムとは少しだけ違います。

私がやりたかったことは**2回連続で同じ場所には絶対に出ない**という実装です。



なのでちょっと面倒でした。


↓↓↓補足(2019.3/11)↓↓↓
>同じエリアに連続出現しないだけで座標は毎回ランダムにしたい

これです！まさにこれ！
コメントありがとうございます！

##考え方
まずゲームオブジェクトを出現させたい位置を分割します。
![randomArea.png](https://qiita-image-store.s3.amazonaws.com/0/244071/d8209485-ad39-2ff9-1b47-e8649df1ac6e.png)

上のとてもわかりやすい図のように分けた場合、
もし0に出現したら次は必ず1、2、3のどこかに出現するようにします。

もっと効率の良い方法があるのかもしれませんが、ちょっと急いでたのでこのやり方で実装しました。

##値を返すメソッドを用意

ランダムな値を渡すとその値と同じ値を返すメソッドを用意しました。
これにより、一度出現したエリアの番号を記録できます。

```C#
 int? RandomArea(int patternNum)
    {
        if (patternNum == 0)
        {
            holeParentPosition = new Vector3(randomX_A, holeParentPosition.y, randomZ_A);
            this.gameObject.transform.localPosition = holeParentPosition;

            return 0;
        }

        if (patternNum == 1)
        {
            holeParentPosition = new Vector3(randomX_B, holeParentPosition.y, randomZ_B);
            this.gameObject.transform.localPosition = holeParentPosition;

            return 1;
        }

        if (patternNum == 2)
        {
            holeParentPosition = new Vector3(randomX_C, holeParentPosition.y, randomZ_C);
            this.gameObject.transform.localPosition = holeParentPosition;

            return 2;
        }

        if (patternNum == 3)
        {
            holeParentPosition = new Vector3(randomX_D, holeParentPosition.y, randomZ_D);
            this.gameObject.transform.localPosition = holeParentPosition;

            return 3;
        }

        return null;

    }
```


##最終的なコード

```C#

    public GameObject hole;

    Vector3 holeParentPosition;

    int[] patternNumber = { 0, 1, 2, 3 };
    int patternArray;
    

    float randomX_A;
    float randomZ_A;

    float randomX_B;
    float randomZ_B;

    float randomX_C;
    float randomZ_C;

    float randomX_D;
    float randomZ_D;

    void Start()
    {
        holeParentPosition = this.gameObject.transform.localPosition;
    }


 void Update()
    {
        patternArray = Random.Range(0, patternNumber.Length);

        randomX_A = Random.Range(0.5f, 4.0f);
        randomZ_A = Random.Range(-5f, -1.5f);

        randomX_B = Random.Range(0.5f, 4.0f);
        randomZ_B = Random.Range(-9f, -5.5f);

        randomX_C = Random.Range(-4.0f, -0.5f);
        randomZ_C = Random.Range(-9f, -5.5f);

        randomX_D = Random.Range(-4.0f, -0.5f);
        randomZ_D = Random.Range(-5f, -1.5f);

        //コルーチン開始(一回で抜ける)
        if (ThisProjectSingleton.Instance.isGameStart)
        {
            StartCoroutine(HoleRandomCoroutine());
            ThisProjectSingleton.Instance.isGameStart = false;
        }


    }

    int? RandomArea(int patternNum)
    {
        if (patternNum == 0)
        {
            holeParentPosition = new Vector3(randomX_A, holeParentPosition.y, randomZ_A);
            this.gameObject.transform.localPosition = holeParentPosition;

            return 0;
        }

        if (patternNum == 1)
        {
            holeParentPosition = new Vector3(randomX_B, holeParentPosition.y, randomZ_B);
            this.gameObject.transform.localPosition = holeParentPosition;

            return 1;
        }

        if (patternNum == 2)
        {
            holeParentPosition = new Vector3(randomX_C, holeParentPosition.y, randomZ_C);
            this.gameObject.transform.localPosition = holeParentPosition;

            return 2;
        }

        if (patternNum == 3)
        {
            holeParentPosition = new Vector3(randomX_D, holeParentPosition.y, randomZ_D);
            this.gameObject.transform.localPosition = holeParentPosition;

            return 3;
        }

        return null;

    }

    IEnumerator HoleRandomCoroutine()
    {
        int? tmpNum = 0;
        int? memoryNum = 0;
        while (/*ゲームオーバーの条件を記述*/)
        {
            yield return new WaitForSeconds(0.5f);
            tmpNum= RandomArea(patternNumber[patternArray]);

            //もしランダムな数字( tmpNum)が前回(memoryNum)と一致したら通過。別の数字をtmpNumに代入して抜ける
            while (tmpNum == memoryNum)
            {
                yield return new WaitForEndOfFrame();
                tmpNum = RandomArea(patternNumber[patternArray]);
            }
            memoryNum = tmpNum;
            hole.SetActive(true);
            

            //ホールにボールが入るまで待つ
            yield return new WaitUntil(() => ThisProjectSingleton.Instance.isHoleEnter);
            ScoreText.ScoreAdd();

            //ホールが消える
            yield return new WaitForSeconds(0.5f);
            hole.SetActive(false);
            ThisProjectSingleton.Instance.isHoleEnter = false;
        }
    }
```
いま自分で読み返しても読みづらいしもっといい方法がありそうです。
こんな方法もあるよ～って方、コメントください。


##unity1week
[unity1week](https://unityroom.com/unity1weeks)という企画がありまして、
その名の通りUnityを用いて一週間でゲームを作ろうというおもしろい企画です。

私も参加するつもりなのですが、
そこで作るのはWebGLというブラウザ上で起動する形式です。

**せっかく作ったのにビルドとかアップロードの仕方がわからない！**
と本番でならないようにunity1dayと称して、
簡単なゲームを作り[unityroom](https://unityroom.com/)にテストアップロードしました。

今回紹介した**ゲームオブジェクトを毎回違う場所に配置する方法**も用いているので
よかったら覗いてみてください。↓

[Lava is hot(訳:溶岩はあったかいよ)](https://unityroom.com/games/kento_no_game)

人のコード見た後にそのゲームをプレイするの結構おもしろいです。