Menu
CoddyTech

Niemals flach

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

Ein Ball kann fast seitwärts fliegen: Ein Abpraller an der Ecke eines Steins oder ein Stoß durch einen anderen Ball kann ihn nahezu waagerecht zurücklassen, sodass er immer wieder das Spielfeld überquert, ohne herunterzukommen. Das Spiel kommt zum Stillstand, während der Spieler darauf wartet, dass der Ball herunterkommt. Die Lösung gehört in die Geschwindigkeitskorrektur: Nachdem die Richtung auf die Länge 1 gebracht wurde, setze y auf einen Mindestwert und normalisiere erneut, wenn sein y-Anteil zu klein ist.

Zwei Mathf-Methoden erledigen die Arbeit. Mathf.Abs gibt den Betrag einer Zahl ohne ihr Vorzeichen zurück, sodass ein Test sowohl Bälle erfasst, die nach oben fliegen, als auch solche, die nach unten fliegen. Mathf.Sign gibt -1 für eine negative Zahl und andernfalls 1 zurück, sodass das neue y die Flugrichtung des Balls beibehält: Ein Ball, der nach unten fliegt, fliegt weiterhin nach unten.

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

Rechne es mit einem Mindestwert von 0.3 und der Richtung (0.99, -0.12, 0) durch. Der Betrag von y, 0.12, liegt unter 0.3, also wird y zu -0.3, und (0.99, -0.3, 0) normalisiert ergibt ungefähr (0.96, -0.29, 0): weiterhin nach rechts und unten, jetzt steil genug, um zurückzukommen. Durch das Normalisieren fällt y wieder ein wenig unter den Mindestwert, und der nächste Schritt hebt es wieder an, sodass es ein wenig unter 0.3 bleibt. Steilere Richtungen bleiben unverändert.

challenge icon

Aufgabe

Mittel
  1. Füge public float minVertical = 0.3f zu Ball hinzu.
  2. Bestimme in FixedUpdate() die Richtung: die normalisierte Geschwindigkeit. Wenn der Betrag ihres y-Werts kleiner als minVertical ist, setze y mit dem Vorzeichen von y auf minVertical und normalisiere die Richtung erneut.
  3. Setze dann wie zuvor die Geschwindigkeit auf die Richtung multipliziert mit speed.

Drücke Play und dann Check.

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);
    }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Unity-Spiel: Brick Breaker