# ボール跳ね返す角度をコントロールする

## 目的

今の作りだと、ボールがパドルを当たると、入射角を反転し、外向角になるだけで、プレーヤーがボール行かせたい方位を変えることができない。ある程度、ボールを行き先をコントロールできるように、パドルの「当たる部分」によって、跳ね返す向きを調整する処理を入れましょう。

![image.png](https://class.illogic.games/uploads/images/gallery/2026-04/scaled-1680-/kw1image.png)

これで、ボールがパドルの左側に当たると、ボールが左に行く。真ん中を当たると、真上に返す。右側を当たると、右に行くようにする。

### 解決のアイディア

ボールとパドルの相対位置がポイント。ボールが衝突したら、パドルの位置とボールの位置を使い、その向きに返せば良いでしょう：

![image.png](https://class.illogic.games/uploads/images/gallery/2026-04/scaled-1680-/uqWimage.png)

## スクリプト

ボールを跳ね返す責任を持つ「BallRebound」を作成しましょう。衝突に時（`OnCollisionEnter2D`）ボールの速度の向きを変えれば良いでしょう。

```c#
// ボールの跳ね返す角度を制御する
public class BallRebound : MonoBehaviour
{
    // 衝突のとき
    private void OnCollisionEnter2D(Collision2D other)
    {
        // "other" がボールでしょう
        // なので、RigidBodyを取得し、速度を変えましょう
        Rigidbody2D rb = other.gameObject.GetComponent<Rigidbody2D>();
        
        // 速度ベクトルの長さを保持するので、求めましょう
        float speed = rb.linearVelocity.magnitude;
        
        // 新しい向きは、ボールの位置とパドルの位置の差分で求める
        Vector2 direction = other.transform.position - transform.position;
        
        // 長さが１（単位ベクトル）にする
        direction.Normalize();
        
        // 新しい速度は、前の速度（量）× 新しい向きにする
        rb.linearVelocity = direction * speed;
    }
}
```

このスクリプトを「player」にアタッチし、試してみると、ボールをうまくコントロールできるようになったが、パドルが壁とぶつけると：

![image.png](https://class.illogic.games/uploads/images/gallery/2026-04/scaled-1680-/hBvimage.png)

[![image.png](https://class.illogic.games/uploads/images/gallery/2026-04/scaled-1680-/7eQimage.png)](https://class.illogic.games/uploads/images/gallery/2026-04/7eQimage.png)

のエラーが発生してしまう。

### エラーの解決：タグを使用

今の処理だと「衝突したら」だけなので、何と衝突するのかを確認していない。ボールの場合は、ボールのリジッドボディを取得し、速度を問題なく変えられるが、壁と衝突するとバグってしまう。

なぜなら、壁がリジッドボディがなく、`GetComponent<Rigidbody2D>()` を呼び出すが失敗してしまうから。

なので、衝突したときに、何と衝突したのかを「タグ」で確認しましょう。まず、スクリプトを修正し、「Ball」タグがなければ、何も処理しない部分を追加しましょう。

```c#
// ボールの跳ね返す角度を制御する
public class BallRebound : MonoBehaviour
{
    // 衝突のとき
    private void OnCollisionEnter2D(Collision2D other)
    {
        // "other"が "Ball"タグがないか？
        if (!other.gameObject.CompareTag("Ball"))
        {
            return; // メソッドがここで終わり
        }
        
        // "other" がボールでしょう
        // なので、RigidBodyを取得し、速度を変えましょう
        Rigidbody2D rb = other.gameObject.GetComponent<Rigidbody2D>();
        
        // 速度ベクトルの長さを保持するので、求めましょう
        float speed = rb.linearVelocity.magnitude;
        
        // 新しい向きは、ボールの位置とパドルの位置の差分で求める
        Vector2 direction = other.transform.position - transform.position;
        
        // 長さが１（単位ベクトル）にする
        direction.Normalize();
        
        // 新しい速度は、前の速度（量）× 新しい向きにする
        rb.linearVelocity = direction * speed;
    }
}
```

そして、ボールのプレハブを編集し、「Ball」タグをつけましょう（小文字・大文字の注意を！）：

![image.png](https://class.illogic.games/uploads/images/gallery/2026-04/scaled-1680-/6JBimage.png)

これで問題解決！