Không bao giờ nhàm chán
Bài học 10 trên 19 trong khóa học Trò chơi Unity: phá gạch của Coddy.
Cú nảy trúng góc viên gạch có thể khiến bóng bay gần như ngang, liên tục băng qua sân trong khi người chơi chờ đợi. Cách khắc phục nằm ở phần sửa tốc độ: nếu thành phần y của hướng quá nhỏ, hãy đặt nó ở mức tối thiểu rồi chuẩn hóa lại.
Mathf.Abs cho biết độ lớn của một số mà không xét dấu, vì vậy một phép kiểm tra sẽ bắt được bóng bay lên lẫn bay xuống. Mathf.Sign trả về -1 với số âm và 1 trong các trường hợp còn lại, nên bóng đang bay xuống vẫn tiếp tục bay xuống.
Debug.Log(Mathf.Abs(-0.12f)); // 0.12
Debug.Log(Mathf.Sign(-0.12f)); // -1Với mức tối thiểu là 0.4, hướng (0.99, -0.12, 0) có y bằng -0.4 và sau khi chuẩn hóa sẽ xấp xỉ (0.93, -0.37, 0): bóng vẫn bay sang phải và xuống dưới, nhưng giờ hướng đủ dốc để quay lại. Các hướng dốc hơn sẽ được giữ nguyên.
Thử thách
Trung bìnhĐừng để bóng bay gần như ngang qua sân.
- Trong
Ball, thêmpublic float minVertical = 0.3f; - Trong FixedUpdate, lấy
Vector3 direction = rb.linearVelocity.normalized;. NếuMathf.Abs(direction.y) < minVertical, đặtdirection.y = Mathf.Sign(direction.y) * minVertical;rồi chuẩn hóa lại. - Đặt
rb.linearVelocity = direction * speed;
Nhấn Chơi: bóng sẽ không bay ngang qua sân trong thời gian dài. Sau đó nhấn Kiểm tra.
Tự làm thử
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);
}
}
Tất cả bài học trong Trò chơi Unity: phá gạch
3Luồng trò chơi
Điểm số và mạngTự luyện tập: Playground Unity