Unityで簡単なゲームを作ってみた

##作成したゲーム
- 上から降ってくる岩を打ち落として、得点を稼ぐシューティングゲーム。岩が画面外に出てしまったらゲームオーバー。

- Unityのバージョンは2018.4.19f1

- プレイヤー移動はキーボード入力
- 弾が岩に当たったら爆発のエフェクト
- 弾を発射した際、Trail Rendererを使って弾の軌跡を出す
- UIで得点を表示し、岩が画面外に行ったときにゲームオーバーを表示を出す

###用意したもの
- プレイヤー、障害物（岩とか）、弾、弾の軌跡、背景

>[使用した素材](https://www.dropbox.com/s/ly7wl2phjihj041/SampleShooting_Material.zip?dl=0)


##ソースコード
### プレイヤー（ロケット）を動かすスクリプト


```RocketController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RocketController : MonoBehaviour
{
    public GameObject bulletPrefab;

    void Update()
    {
        if (Input.GetKey(KeyCode.LeftArrow))
        {
            transform.Translate(-0.1f, 0, 0);
        }

        if (Input.GetKey(KeyCode.RightArrow))
        {
            transform.Translate(0.1f, 0, 0);
        }

        if (Input.GetKeyDown(KeyCode.Space))
        {
            Instantiate(bulletPrefab, transform.position, Quaternion.identity);
        }
    }
}
```
####Instantiate関数
```cs
  Instantiate(bulletPrefab,transform.position,Quaternion.identify);
//Instantiate(第１関数,第２関数,第３関数);
```
- この関数ではPrefabからインスタンスを作り、任意の位置に生成する関数です
- 第１関数にPrefab、第２関数にインスタンスを作成したい位置、第３関数にはインスタンスの回転角を指定します
- 今回は弾のPrefab（bulletPrefab）を複製して発射したいのでこれを第１関数に、これをプレイヤーの位置に生成したい　ので第２関数はtransform.position、第３関数の回転はQuaternion.identifyにすることで無回転になります


---
###岩の制御
 
 * 岩を落とすスクリプト

```RockController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RockController : MonoBehaviour
{
    float fallSpeed;
    float rotSpeed;
    
    void Start()
    {
        this.fallSpeed = 0.01f + 0.1f * Random.value;
        this.rotSpeed = 5f + 3f * Random.value;
    }

    
    void Update()
    {
        transform.Translate(0, -fallSpeed, 0, Space.World);
        transform.Rotate(0, 0, rotSpeed);

        if (transform.position.y < -5.5f)
        {
            GameObject.Find("Canvas").GetComponent<UIController>().GameOver();
            Destroy(gameObject);
        }
    }
}
```
####Translate関数
```cs

  transform.Translate(0, -fallSpeed, 0, Space.World);
//transform.Translate(x, y, z, relative to);
```
- 最初の３つの値はxyzどの軸に沿って移動するかという意味で、最後のrelative toにはSpace.WorldやSpace.Selfなどが入ります。Space.Worldにした場合、ワールド座標になります。ワールド座標とは原点から見た座標のことです。
- 今回の場合、fallSpeedに従って落ちてきてほしいのでy軸のみ値が入っています

---
* ランダムに岩を生成するスクリプト

```RockGenerator.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RockGenerator : MonoBehaviour
{
    public GameObject rockPrefab;
    
    void Start()
    {
        InvokeRepeating("GenRock", 1, 1);
    }

    void GenRock()
    {
        Instantiate(rockPrefab, new Vector3(-2.5f + 5 * Random.value, 6, 0), Quaternion.identity);
    }
}
```
####InvokeRepeating関数
```cs
InvokeRepeating("GenRock", 1, 1);
//InvokeRepeating(第１関数, n, m);
```
- この関数はとても便利な関数です。第１関数に指定したものを、n秒後にm回呼び出す関数です。
- 今回はGenRockという関数を１秒に１回呼び出したいのでこのようになります

---
###背景を動かすスクリプト
 
```BackgroundController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BackgroundController : MonoBehaviour
{   
    void Update()
    {
        transform.Translate(0, -0.03f, 0);
        if (transform.position.y < -4.9f)
        {
            transform.position = new Vector3(0, 4.9f, 0);
        }
    }
}
```
* 背景の大きさは決まっているのである一定のところまで移動したら、戻るようにif文で設定しています

---
###発射する弾の制御

```BulletController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BulletController : MonoBehaviour
{
    public GameObject explosionPrefab;      //爆発エフェクトのPrefab
    
    void Update()
    {
        transform.Translate(0, 0.2f, 0);

        if (transform.position.y > 5)
        {
            Destroy(gameObject);
        }
    }

    void OnTriggerEnter2D(Collider2D coll)
    {
        //衝突したときにスコアを更新する
        GameObject.Find("Canvas").GetComponent<UIController>().AddScore();

        //爆発エフェクトを生成
        GameObject effect = Instantiate(explosionPrefab, transform.position, Quaternion.identity) as GameObject;
        Destroy(effect, 1.0f);

        Destroy(coll.gameObject);
        Destroy(gameObject);
    }
}
```
#### ややこしい部分の解説

```cs

//爆発エフェクトを生成
 GameObject effect = Instantiate(explosionPrefab, transform.position, Quaternion.identity) as GameObject;
 Destroy(effect, 1.0f);
```
* Instantiate関数でGameObjectとしてキャストすることで、爆発エフェクトを加える
* その後のDestroy関数でそのオブジェクトを消す。第２引数はオブジェクトを破壊するまでの時間（秒）です


---

###UIの制御

```UIController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class UIController : MonoBehaviour
{
    int score = 0;
    GameObject scoreText;
    GameObject gameOverText;
    public void GameOver()
    {
        this.gameOverText.GetComponent<Text>().text = "GameOver";
    }
    public void AddScore()
    {
        this.score += 10;
    }
   
    void Start()
    {
        this.scoreText = GameObject.Find("Score");
        this.gameOverText = GameObject.Find("GameOver");
    }

    void Update()
    {
        scoreText.GetComponent<Text>().text = "Score:" + score.ToString("D4");
    }
}
```
####スコアの更新

```cs
scoreText.GetComponent<Text>().text = "Score:" + score.ToString("D4");
```
* UIのテキスト部分に「Score:0000」と表示するためにscoreText.GetComponent<Text>.textで情報を入手する
* score.ToString("D4")は整数を４桁表示するという意味です


###作成したゲーム

![簡単なゲーム制作2D.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534857/06321f08-55a1-d46e-f640-1c6abea50a3c.gif)

##問題点
* 同じ場所で弾を連射すると、弾同士がぶつかってしまいそこに爆発エフェクトがでてしまう。

##参考させていただいたサイト
>[おもちゃラボ　【Unity入門】60分でつくるシューティングゲーム](http://nn-hokuson.hatenablog.com/entry/2016/07/04/213231)

##追記
* GitHubにコード上げました！

>[GitHub](https://github.com/sakahiro-yy/UnityEasyGame-2D-)