Menu
CoddyTech

Nie flach

Lektion 10 von 19 im Kurs Unity-Spiel: Brick Breaker von Coddy.

Ein Abpraller an einer Backsteinecke kann den Ball fast waagerecht weiterfliegen lassen, sodass er immer wieder das Spielfeld überquert, während der Spieler wartet. Die Lösung gehört zur Geschwindigkeitskorrektur: Ist der y-Anteil der Richtung zu klein, setze ihn auf einen Mindestwert und normalisiere erneut.

Mathf.Abs liefert den Betrag einer Zahl ohne ihr Vorzeichen, sodass ein Test Bälle erfasst, die nach oben oder unten fliegen. Mathf.Sign liefert -1 für eine negative Zahl und andernfalls 1, sodass ein nach unten fliegender Ball weiterhin nach unten fliegt.

Debug.Log(Mathf.Abs(-0.12f));   // 0.12
Debug.Log(Mathf.Sign(-0.12f));  // -1

Bei einem Mindestwert von 0.4 erhält die Richtung (0.99, -0.12, 0) den y-Wert -0.4 und ergibt normalisiert etwa (0.93, -0.37, 0): weiterhin nach rechts und unten, nun steil genug, um zurückzukommen. Steilere Richtungen bleiben unverändert.

challenge icon

Aufgabe

Mittel

Verhindere, dass der Ball lange fast waagerecht über das Spielfeld fliegt.

  1. Füge in Ball public float minVertical = 0.3f; hinzu.
  2. Weise in FixedUpdate Vector3 direction = rb.linearVelocity.normalized; zu. Wenn Mathf.Abs(direction.y) < minVertical gilt, setze direction.y = Mathf.Sign(direction.y) * minVertical; und normalisiere erneut.
  3. Setze rb.linearVelocity = direction * speed;

Drücke auf „Spielen“: Der Ball fliegt nie lange waagerecht über das Spielfeld. Klicke dann auf „Prüfen“.

Probier es selbst

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;
    }

    public void ResetToPaddle()
    {
        launched = false;
        rb.linearVelocity = Vector3.zero;
    }

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

    void OnCollisionEnter(Collision collision)
    {
        if (!collision.gameObject.CompareTag("Paddle")) return;
        float offset = transform.position.x - collision.transform.position.x;
        float halfWidth = collision.collider.bounds.size.x / 2f;
        float x = Mathf.Clamp(offset / halfWidth, -1f, 1f);
        rb.linearVelocity = new Vector3(x, 1f, 0f).normalized * speed;
    }

    void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("DeathZone")) GameManager.Instance.BallLost(this);
    }
}

Alle Lektionen in Unity-Spiel: Brick Breaker

Übe selbstständig: Unity-Playground