魚釣り(魚つらない)ゲームを作ってみた　後編

[【完走目指す】初心者が25日で強くなる Advent Calendar 2022
](https://qiita.com/advent-calendar/2022/aruhitoganbaru)
14日目です。昨日の続きです。
# 魚つらない
魚釣りゲームって結構難しいんですね。
時間がかかりすぎて大学の課題とテストがいよいよ危なくなってきたので、魚つらないゲームにします。全くあきらめてないので（できなくて結構悔しかったので）時間があるときに、魚釣りづくりはリベンジします。ちなみに、惜しいところまで行ってました。波の表面で、太陽の光を反射させる表現が作れなかったことが原因です。
# では何を作るのか
球を転がして、魚を倒すボウリングにします。
一応海関連なので、個人的にはOKです。
# 現状
![Unity　魚釣り.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961125/f40d5da8-f4f2-87c4-4626-f31861960748.png)
ひどい有様です。これを戻していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961125/91c7d542-582f-7b3d-e443-81f8d662c496.png)
これですっきり。
# 中身
こんな感じに作ろうと思っています。
![魚ボウリング.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961125/6c08fdb1-9944-3b01-3d3f-16d307b8ce3b.png)
これがうまくできないと、明日以降の予定がつぶれます。頑張って作ります。
まずは、動く魚を作ります。
1行だけ、Update内に追加します。

```

```
これで、魚は動くでしょうか。　
![スクリーンショット_20221214_163027.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961125/b2ede28f-1eee-d22a-083f-3cd8dd79d06c.png)
画像じゃ動いてるかわからないですが、
###### 流石に動きました。　
# 衝突　
このままでは、魚はどこまでも左に進んでしまいます。なのでどこかで右に移動しなければなりません。
反転させた魚の画像を入れて逆方向に進ませることも考えましたが、折角なので衝突判定を使って右にワープさせます。
ちなみに、衝突は後でまた使います。
参考：

https://www.sejuku.net/blog/58775

まず、以下の文を追加します。
```
 private void OnCollisionEnter(Collision collision)
    {
       
        if (collision.gameObject.tag == "Reset")
        {
            this.transform.position=new Vector3(1200, 5, 0);
        }
```
判定するためには、OnCollisionEnterを使うみたいです。
さらにif文で何と衝突したかを追加すると、衝突したものによって挙動を変えられるみたいです。
今回は「Reset」のタグが付いた、衝突を判定してくれるものを作りました。
# （タグ）
衝突とかの判定に使われるっぽいです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961125/09161785-4238-20d2-a404-915e6b17a668.png)
Tagって書いてあるところから簡単にタグを作れました。
新しいタグを作るときは、Add Tag…　> Tagsの所の＋ボタンを押して、名前を登録するだけでした。簡単。

話を戻します。

Resetのタグが付いたものに魚がぶつかると、(1200, 5, 0)の位置に転生します。
Rigidbodyとかいうやつが必要らしいので、つけました。後、Colliderが必要そうでしたが、Mesh Colliderが付いていたので大丈夫そうです。
### 結果
![スクリーンショット_20221214_164358.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961125/b677b79c-6891-81d5-c537-39b71697baa0.png)
魚が脱走しました。何故だ。
## 原因
Box Colliderもつけたら、うまくいきました。
衝突するもの、されるものの双方にBox ColliderとRigidBodyが必要そうです。
直しました。
動きました。
ところが、魚が同じスタート地点から始まることでBoxCollider同士がぶつかって、変な方向へ進んでしまいました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961125/2781b661-e8a6-480d-efd4-aa50abd370a7.png)

修正
以下のように変えます。
面倒なので、全文貼っておきます。

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

public class Sakana : MonoBehaviour
{
    float ZH;
    
    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        this.transform.Translate(-(Time.deltaTime*50), 0, 0);
    }
    private void OnCollisionEnter(Collision collision)
    { ZH = this.transform.position.z;
        
        if (collision.gameObject.tag == "Reset")
        { this.transform.Rotate(0, 0, 0); 
            this.transform.position=new Vector3(300, 5, ZH);
        }
    }
}
```

再スタート時、z軸が0になってたのを自分がさっきまでいた位置に直しました。
後、向きも初期位置（0,0,0）に直しました
これでいけるでしょう。

結果
一応いけた。
なんか斜めに動いてる気がするけど、ちゃんとボウリング玉と衝突できる範囲内なので今回は良しとします。

次。
# ボールを動かす
ボタンを押すと、ボールが動くようにします。
はじめ、
```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Main : MonoBehaviour
{
    public GameObject Button;
    public GameObject Tama;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    public void OnClick()
    {
        Tama.transform.position = new Vector3(0,100,-400);
        Tama.transform.Translate(0, 0, Time.deltaTime * 200);

    }
}
```
と書いていましたが、ボールがその場から動かなかったので（設定はちゃんとしましたが）修正しました。魚が動くスクリプトから魚を動かす部分を一行コピペしたら動くようになりました。何故だ!


12/15
とりあえず、この日の朝までに出来上がった全体像をご覧ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961125/cc7eb805-e03e-322a-dc10-021a6fad64c5.png)

昼にやっと出来上がりました。
いろいろ載せておきます。
ボールにつけたスクリプト中身
１，
```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Ball : MonoBehaviour
{
    public bool As;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
       
        if (As == true)
        {
           
            this.transform.Translate(0, 0, (Time.deltaTime * 50));
        }
    }
}
```
```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BallHantei : MonoBehaviour
{
    public Score SC;
    public Syk Sk;
    public Ball bl;
    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }

    private void OnTriggerEnter(Collider collision)
    {
        if (collision.gameObject.tag == "Sakana1")
        {
            Debug.Log("A");
            SC.Scr = SC.Scr + 1;
        }
        if (collision.gameObject.tag == "Sakana2")
        {
            {
                Debug.Log("B");
                SC.Scr = SC.Scr + 2;
            }
        }
        if (collision.gameObject.tag == "Reset")
        {
            bl.As = false;
            Sk.As = Sk.As + 1;
      
            this.transform.position = new Vector3(0, 1, -240);
            this.GetComponent<Rigidbody>().velocity = Vector3.zero;
            this.GetComponent<Rigidbody>().angularVelocity = Vector3.zero;
            this.transform.Translate(0, 0, 0);
        }
    }
}
```
ゲームシステム中身
```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class Syk : MonoBehaviour
{
    public int As;
    public GameObject button;
    public GameObject Fin;
    public Score Re;
    // Start is called before the first frame update
    void Start()
    {
        As = 0;
        Fin.SetActive(false);
    }

    // Update is called once per frame
    void Update()
    {
        if (As == 0 || As == 2)
        {
            button.SetActive(true);

        }
        else
        {
            button.SetActive(false);
        }
        if (As == 4)
        {
            Fin.SetActive(true);
           
        }
    }
}
```
魚
```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sakana : MonoBehaviour
{
    float ZH;
    
    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        this.transform.Translate(-(Time.deltaTime*50), 0, 0);
    }
    private void OnTriggerEnter(Collider collision)
    { ZH = this.transform.position.z;
        
        if (collision.gameObject.tag == "Reset")
        {
           
            this.GetComponent<Rigidbody>().angularVelocity = Vector3.zero;
            this.transform.position=new Vector3(95, 5, ZH);
            this.transform.Rotate(0, 0, 0);
           
        }
        if (collision.gameObject.tag == "ball")
        {
          
            this.gameObject.SetActive(false);
        }
    }
}
```
スコア、回数
```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.UI;
public class Nowkaisuu : MonoBehaviour
{public TextMeshProUGUI Ks;
    public Syk Sk;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if (Sk.As <= 1)
        {
            Ks.text = "1";
        }
        else
        {
            Ks.text = "2";
        }
        
    }
}
```

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.UI;
public class Score : MonoBehaviour
{public TextMeshProUGUI Tx;
    public int Scr = 0;
        public Syk Sk;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        Tx.text = Scr.ToString();
        if (Sk.As == 4)
        {
            this.GetComponent<RectTransform>().anchoredPosition=new Vector3(80, -60, 0);
           
        }
    }
}
```
ボタン
```

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

public class Main : MonoBehaviour
{
    
    public GameObject Tama;
    public Syk Sk;
    public Ball Bl;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    
    void Update()
    {
        
        
    }
    public void OnClick()
    {
        Tama.SetActive(true);
        Sk.As = Sk.As + 1;
        Bl.As =true;
      
    }
}

```
全体像
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961125/67511235-137b-e085-2270-8fdfba4121d3.png)
スタートを押すと、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961125/59f5d0ad-ef7f-161b-fe9b-d64989274c2f.png)
ボールが動いて
魚に当たると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961125/8fd118ec-b853-b14c-b42b-5e198e5276e4.png)
スコアが増える。
２ラウンド制。
# 時間がかかった原因
### １．衝突の判定
これに時間を取られました。
衝突は、
```
private void OnCollisionEnter(Collision collision){}

```
これなんですが、
すり抜けは、
```
private void OnTriggerEnter(Collider collision)
```
これです。
違いが二つあって、
 OnCollisionEnter　が　OnTriggerEnter　になります
あと()内の、
Collision collision　が　Collider collisionに変化します。
これを知らないままだったので結構時間を取られました。
ちなみに、衝突すると変な方向を向いてしまったので今回はすり抜け判定を使いました。
### ２.魚の動き
これのせいで約１日半時間を取られました。
これのせいです。
実は魚に
```
 this.transform.Translate(-(Time.deltaTime*50), 0, 0);
```
これを取り付けているんですが、
このままだと一定の方向に動き続けるだけなので、向きが変わると思ってもいない方向へ行ってしまいます。（あたりまえだけど）
つまり、
![魚向き１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961125/3e15638e-bf27-f587-be87-f52b9938da07.png)
これが
![魚向き２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961125/a0254a04-47ef-14cc-1247-816521e10723.png)
こうなったわけです。
何かにぶつかるとすぐに向きを変えてしまいます。
かなり面倒でした。

# まとめ
カメラを２つ使って画面を２分割にするやり方は、調べれば簡単にわかると思うし、躓くところもなさそうで、また記事の量も多くなるので省略します。
時間があったらリメイクします。

14日目（１５日だけど）　おわり