Celuj paletką
Lekcja 4 z 16 w kursie Gra w Unity: Zbijanie klocków w Coddy.
Przy idealnym odbiciu gracz nie może celować: piłka opuszcza paletkę pod takim samym kątem, pod jakim do niej doleciała. W grach typu Brick Breaker to paletka decyduje o kierunku. Trafienie blisko lewego końca wysyła piłkę w górę i w lewo, trafienie w środek — prosto w górę, a im dalej od środka, tym szerszy kąt.
Zamień miejsce trafienia na liczbę od -1 na lewym końcu do 1 na prawym końcu: poziome przesunięcie piłki względem środka paletki podziel przez połowę szerokości paletki. Załóżmy, że paletka ma 4 jednostki szerokości, a jej środek znajduje się w x = 2, zaś piłka trafia w x = 3. Przesunięcie wynosi 1, połowa szerokości wynosi 2, więc otrzymujemy liczbę 0.5, a nowy kierunek to 0.5 w poziomie i 1 w górę, czyli (0.5, 1, 0), po normalizacji. Trafienie dokładnie w koniec daje 1 lub -1, co odpowiada kątowi 45 stopni od kierunku prosto w górę. Ogranicz tę liczbę do tego zakresu, ponieważ piłka może dotknąć rogu paletki nieco poza jej końcem.
Funkcja OnCollisionEnter piłki jest wywoływana po obliczeniu odbicia przez fizykę, więc ustawiona w niej prędkość zastępuje poprzednią. Ściany wysyłają tę samą wiadomość i powinny zachować zwykłe odbicie, więc najpierw sprawdź, co zostało trafione. collision.collider.bounds to prostopadłościan zajmowany przez collider w świecie, z uwzględnieniem skali:
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);
}Wyzwanie
ŁatwyDodaj OnCollisionEnter(Collision collision) do Ball:
- Nie rób nic, chyba że trafiony obiekt ma tag
Paddle. - Oblicz
x: od współrzędnej x piłki odejmij współrzędną x paletki, a następnie podziel wynik przez połowę szerokości paletki (collision.collider.bounds.size.x); ogranicz wartość do przedziału od -1 do 1. - Ustaw prędkość Rigidbody na
new Vector3(x, 1f, 0f), znormalizuj ją i pomnóż przezspeed.
Naciśnij Play, odbij piłkę przy obu końcach paletki, a następnie kliknij Check.
Spróbuj swoich sił
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;
}
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.