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

これで、ボールがパドルの左側に当たると、ボールが左に行く。真ん中を当たると、真上に返す。右側を当たると、右に行くようにする。
解決のアイディア
ボールとパドルの相対位置がポイント。ボールが衝突したら、パドルの位置とボールの位置を使い、その向きに返せば良いでしょう:

スクリプト
ボールを跳ね返す責任を持つ「BallRebound」を作成しましょう。衝突に時(OnCollisionEnter2D)ボールの速度の向きを変えれば良いでしょう。
// ボールの跳ね返す角度を制御する
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;
// 長さが1(単位ベクトル)にする
direction.Normalize();
// 新しい速度は、前の速度(量)× 新しい向きにする
rb.linearVelocity = direction * speed;
}
}
このスクリプトを「player」にアタッチし、試してみると、ボールをうまくコントロールできるようになったが、パドルが壁とぶつけると:

のエラーが発生してしまう。
エラーを解決:タグを使用
今の処理だと「衝突したら」だけなので、何と衝突するのかを確認していない。ボールの場合は、ボールのリジッドボディを取得し、速度を問題なく変えられるが、壁と衝突するとバグってしまう。
なぜなら、壁がリジッドボディがなく、GetComponent<Rigidbody2D>() を呼び出すが失敗してしまうから。
なので、衝突したときに、何と衝突したのかを「タグ」で確認しましょう。まず、スクリプトを修正し、「Ball」タグがなければ、何も処理しない部分を追加しましょう。
// ボールの跳ね返す角度を制御する
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;
// 長さが1(単位ベクトル)にする
direction.Normalize();
// 新しい速度は、前の速度(量)× 新しい向きにする
rb.linearVelocity = direction * speed;
}
}
そして、ボールのプレハブを編集し、「Ball」タグをつけましょう(小文字・大文字の注意を!):

これで問題解決!
