Menu
CoddyTech

Jamais plat

Leçon 10 sur 19 du cours Jeu Unity : casse-briques de Coddy.

Un rebond sur le coin d’une brique peut laisser la balle presque à l’horizontale, traversant le terrain encore et encore pendant que le joueur attend. La correction se fait dans la correction de la vitesse : si la composante y de la direction est trop faible, définis-la à une valeur minimale puis normalise à nouveau.

Mathf.Abs donne la valeur absolue d’un nombre, sans son signe, donc un seul test détecte les balles qui montent et celles qui descendent. Mathf.Sign donne -1 pour un nombre négatif et 1 sinon, donc une balle qui descend continue de descendre.

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

Avec un minimum de 0.4, la direction (0.99, -0.12, 0) obtient y -0.4 et, après normalisation, environ (0.93, -0.37, 0) : elle reste dirigée vers la droite et vers le bas, mais est maintenant assez inclinée pour revenir. Les directions plus inclinées ne sont pas modifiées.

challenge icon

Défi

Moyen

Empêche la balle de traverser le terrain presque à l’horizontale.

  1. Dans Ball, ajoute public float minVertical = 0.3f;
  2. Dans FixedUpdate, récupère Vector3 direction = rb.linearVelocity.normalized;. Si Mathf.Abs(direction.y) < minVertical, définis direction.y = Mathf.Sign(direction.y) * minVertical; et normalise à nouveau.
  3. Définis rb.linearVelocity = direction * speed;

Appuie sur « Jouer » : la balle ne traverse jamais longtemps le terrain à l’horizontale. Puis appuie sur « Vérifier ».

Essayez vous-même

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

Toutes les leçons de Jeu Unity : casse-briques

Entraînez-vous par vous-même : Playground Unity