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)); // -1Avec 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.
Défi
MoyenEmpêche la balle de traverser le terrain presque à l’horizontale.
- Dans
Ball, ajoutepublic float minVertical = 0.3f; - Dans
FixedUpdate, récupèreVector3 direction = rb.linearVelocity.normalized;. SiMathf.Abs(direction.y) < minVertical, définisdirection.y = Mathf.Sign(direction.y) * minVertical;et normalise à nouveau. - 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