Unity初めて1ヶ月でブロック崩しを作った時の備忘録

# はじめに
unity初めて1ヶ月も経たない初心者です

この記事の知識を使うだけで以下のようなブロック崩しゲーム(2d)を作成することができます

https://github.com/sakai1250/Block_KUZUSHI_unity

unityで2dゲームを作る時、困った点として
・inspectなどGUI操作を解説してるサイトが少ない
・inspectでの設定とscriptでの設定の違いがあまりよくわからない
・3dゲームの解説は多いが、2dゲームは比較的少ないと感じた
・チュートリアルが英語(大体そうだけど、ほぼ動画なので復習などは面倒)

などがありました。
自分ような独学者かつ参考書買えない貧金な者はチュートリアルやサイトを見ることで勉強しているので、特にGUI操作に困りました…

なのでGUI操作を中心に備忘録を作りたいと思いました。

自分用の備忘録として作ったので、分かりにくかったり、コード任せな説明が多めですが、少しでも誰かの参考になれたらと思い載せました。
もちろん他の(もっと良い)方法もあると思います。

細かく書きすぎるとアップデートで名称が変わったりするので、概念的な部分を書くようにしています。

# 目次
[何かしらの現実の物体を作りたい時](#何かしらの現実の物体を作りたい時)
[重力を変えたい](#重力を変えたい)
[衝突判定](#衝突判定)
[衝突の挙動がおかしい時](#衝突の挙動がおかしい時)
[キーを押して動かしたい時](#キーを押して動かしたい時)
[壁や地面を作りたい時](#壁や地面を作りたい時)
[大量に湧いては消えるようなものを作る時](#大量に湧いては消えるようなものを作る時)
[ブロックの監視など](#ブロックの監視など、個数がゼロになってしまうものの監視)
[選択ボタンを作って押したら何かする](#選択ボタンを作って押したら何かする)
[個数を表示する](#個数を表示する)
[シーンの遷移方法](#シーンの遷移方法)
[シーン間での値の受け渡し(前画面に戻る時に使える)](#シーン間での値の受け渡し)

# 何かしらの現実の物体を作りたい時
左タブのHierarchyからcreate,spriteを選択し、形(circleなど)を選択(オブジェクト作成という)
Hierarchyからオブジェクトを選択し、右タブのinspectからAdd componentでRigid Body 2dを選択(Rigid bodyでも動く)

# 重力を変えたい
Rigid body 2D のgravity scaleから変更

# 衝突判定
〜colliderで、衝突判定 
scriptで、衝突時の反射などを変える
```ball.cs
   private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("Bar"))
        {
            Vector2 direction = (transform.position - collision.transform.position).normalized;
            Bounce(direction);
        }
        else if (collision.gameObject.CompareTag("Wall"))
        {
            Vector2 reflection = Vector2.Reflect(previousVelocity.normalized, collision.contacts[0].normal);
            rb.velocity = reflection.normalized * previousVelocity.magnitude;
        }
        else if (collision.gameObject.CompareTag("Block"))
        {
            Destroy(collision.gameObject); // ブロックを削除する
            BlockManager.Instance.DecreaseBlockCount(); // ブロックの残り個数を減らす

            Vector2 direction = (transform.position - collision.transform.position).normalized;
            Bounce(direction);

        }
    }
```
具体的なコードは以下を参照(自分のコード)
https://github.com/sakai1250/Block_KUZUSHI_unity/tree/main/tetris%2FAssets%2FScripts

# 衝突の挙動がおかしい時
Rigid body 2dのfrictionや、bounceを変える
(変えるには、下タブのAsset内でmaterialを作る)

# キーを押して動かしたい時


```bar.cs
    private void Update()
    {
        float moveHorizontal = Input.GetAxis("Horizontal");
        Vector2 movement = new Vector2(moveHorizontal, 0f) * moveSpeed;
        rb.velocity = movement;

        if (Input.GetKeyDown(KeyCode.Space))
        {
            ResetBar();
        }

    }
```

# 壁や地面を作りたい時
Hierarchyのcreate tilemapを押す
Add componentからtilemap colliderを追加
window,2d,tile palleteを選択
事前に画像をAssetに取り込み、pixel 64にしておく
その画像(sprite)をtile palleteにドラッグし、あとは上のスポイトマークでタイルを選択、絵の具マークを選択し、塗る

tilemap colliderだと衝突挙動が変なので、辺り判定のコードは以下を参照(自分のコード)
https://github.com/sakai1250/Block_KUZUSHI_unity/tree/main/tetris%2FAssets%2FScripts

# 大量に湧いては消えるようなものを作る時
プレファブ化すれば良い
プレファブ化するには、作ったオブジェクトをAssetにドラッグする(青くなる)
タグも付けてしまえば、大量発生して名前が(block(2))とかになっても、同じblockというタグとして衝突判定などができる

# ブロックの監視など、個数がゼロになってしまうものの監視
Hierarchyからcreate emptyにより、空のオブジェクトを作成、個数監視のscriptをアタッチすることで可能

# 選択ボタンを作って押したら何かする
Hierarchyからcanvas,UI,buttonを選択
inspectから、onclick()の+ボタンを押し、オブジェクトをアタッチする(scriptでは無いことに注意する→オブジェクトにscriptをアタッチしておく)
no functionから自作関数を選択

# 個数を表示する
Hierarchyからcanvas,UI,textを選択
個数scriptをアタッチ
```BlockManager.cs
    private void Start()
    {
        blockCount = GameObject.FindGameObjectsWithTag("Block").Length; // ブロックの初期個数を取得する
        UpdateBlockCountText();
    }

    public void DecreaseBlockCount()
    {
        blockCount--;
        UpdateBlockCountText();

        if (blockCount <= 0)
            ResetLevel();
    }

    private void UpdateBlockCountText()
    {
        blockCountText.text = "Blocks: " + blockCount.ToString();
    }
```
以下を参照(自分のコード)
https://github.com/sakai1250/Block_KUZUSHI_unity/tree/main/tetris%2FAssets%2FScripts

text mesh proだと、コードの書き方が少し異なるので注意(コード参照)

# シーンの遷移方法
file,new sceneを選択(saveしておく)
file,build settingsで、scene(〜.unity)をAdd scenesの場所にドラッグしておく

ボタンを押すと遷移するには、ボタンのscriptにて
scene managerを使うことで、簡単に実装可能
```Stage.cs
    public void LoadStage1()
    {
        SceneManager.LoadScene("Stage1");
    }
```
(コード参照)


# シーン間での値の受け渡し
(前画面に戻る時に使える)
public static classを使い、現在のシーンでの値を記憶させることで可能
以下を参照(自分のコード)
https://github.com/sakai1250/Block_KUZUSHI_unity/tree/main/tetris%2FAssets%2FScripts
```GoResume.cs
public static class PreviousScene
{
    public static string previousScene = SceneManager.GetActiveScene().name;
}


public class GoResume : MonoBehaviour
{
    private bool goResume = false;

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            goResume = true;
            PreviousScene.previousScene = SceneManager.GetActiveScene().name;
        }
        
    }
    
    private void FixedUpdate()
    {
        if (goResume)
        {
            goResume = false;
            SceneManager.LoadScene("Resume");
        }
    }
}
```

```Resume.cs
public class Resume : MonoBehaviour
{
    public void LoadTitle()
    {
        SceneManager.LoadScene("Title");
    }
    public void LoadStage()
    {
        SceneManager.LoadScene(PreviousScene.previousScene);
        // SceneManager.LoadScene("Stage1");
        Debug.Log(PreviousScene.previousScene);
    }
}
```

基本的操作はできるようになったので、今度はオリジナルゲームを作成したいと思っています。