Menu
CoddyTech

Aim with the Paddle

Lesson 4 of 16 in Coddy's Unity Game: Brick Breaker course.

With a perfect bounce the player cannot aim: the ball leaves the paddle at the angle it came in. Brick Breaker games let the paddle decide instead. A hit near the left end sends the ball up and to the left, a hit in the middle sends it straight up, and the further from the middle, the wider the angle.

Turn the hit into a number from -1 at the left end to 1 at the right end: the ball's x offset from the paddle's center, divided by half the paddle's width. Say the paddle is 4 units wide with its center at x = 2, and the ball hits at x = 3. The offset is 1, half the width is 2, so the number is 0.5, and the new direction is 0.5 across and 1 up, (0.5, 1, 0), normalized. A hit right on an end gives 1 or -1, which is 45 degrees from straight up. Clamp the number to that range, because the ball can touch the paddle's corner a little past the end.

The ball's OnCollisionEnter runs after the physics has worked out the bounce, so a velocity set there replaces it. Walls send the same message and must keep their plain bounce, so check what was hit first. collision.collider.bounds is the box the collider fills in the world, scale included:

void OnCollisionEnter(Collision collision)
{
    Bounds box = collision.collider.bounds;
    Debug.Log(collision.gameObject.name + " is " + box.size.x + " wide, centered at x = " + box.center.x);
}
challenge icon

Challenge

Easy

Add OnCollisionEnter(Collision collision) to Ball:

  1. Do nothing unless the object hit is tagged Paddle.
  2. Work out x: the ball's x minus the paddle's x, divided by half the paddle's width (collision.collider.bounds.size.x), kept between -1 and 1.
  3. Set the Rigidbody's velocity to new Vector3(x, 1f, 0f), normalized, times speed.

Press Play, catch the ball near each end of the paddle, then Check.

Try it yourself

using UnityEngine;
using UnityEngine.InputSystem;

public class Ball : MonoBehaviour
{
    public Transform paddle;
    public float speed = 9f;

    Rigidbody rb;
    bool launched;

    void Awake()
    {
        rb = GetComponent<Rigidbody>();
        PhysicsMaterial bouncy = new PhysicsMaterial("Bouncy");
        bouncy.bounciness = 1f;
        bouncy.dynamicFriction = 0f;
        bouncy.staticFriction = 0f;
        bouncy.bounceCombine = PhysicsMaterialCombine.Maximum;
        bouncy.frictionCombine = PhysicsMaterialCombine.Minimum;
        GetComponent<Collider>().material = bouncy;
    }

    void Update()
    {
        if (launched) return;
        transform.position = paddle.position + Vector3.up * 0.5f;
        if (Keyboard.current.spaceKey.wasPressedThisFrame) Launch(new Vector3(0.3f, 1f, 0f));
    }

    public void Launch(Vector3 direction)
    {
        launched = true;
        rb.linearVelocity = direction.normalized * speed;
    }

    void FixedUpdate()
    {
        if (!launched) return;
        rb.linearVelocity = rb.linearVelocity.normalized * speed;
    }
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Unity Game: Brick Breaker