لا تبقَ مسطحًا
الدرس 10 من 19 في دورة لعبة Unity: كاسر الطوب على Coddy.
قد تؤدي ارتطامة بزاوية لبنة إلى جعل الكرة تتحرك أفقياً تقريباً، فتقطع الملعب ذهاباً وإياباً بينما ينتظر اللاعب. يكمن الحل في تصحيح السرعة: إذا كان الجزء y من الاتجاه صغيراً جداً، فعيّنه إلى حد أدنى ثم أعد التطبيع.
تعطي Mathf.Abs مقدار العدد من دون إشارته، لذا يكفي اختبار واحد لاكتشاف الكرات المتجهة إلى أعلى أو إلى أسفل. وتعطي Mathf.Sign القيمة -1 للعدد السالب و1 خلاف ذلك، لذا تظل الكرة المتجهة إلى أسفل متجهة إلى أسفل.
Debug.Log(Mathf.Abs(-0.12f)); // 0.12
Debug.Log(Mathf.Sign(-0.12f)); // -1عند استخدام حد أدنى مقداره 0.4، يصبح y للاتجاه (0.99, -0.12, 0) هو -0.4، وبعد التطبيع يصبح تقريباً (0.93, -0.37, 0): يظل إلى اليمين وإلى أسفل، لكن بزاوية حادة بما يكفي للعودة. أما الاتجاهات الأكثر انحداراً فتُترك كما هي.
التحدي
متوسطامنع الكرة من عبور الملعب وهي تتحرك بشكل أفقي تقريبًا.
- في
Ball، أضفpublic float minVertical = 0.3f; - في FixedUpdate، خذ
Vector3 direction = rb.linearVelocity.normalized;. إذا كانMathf.Abs(direction.y) < minVertical، فعيّنdirection.y = Mathf.Sign(direction.y) * minVertical;ثم أعد التطبيع. - عيّن
rb.linearVelocity = direction * speed;
اضغط «العب»: لن تعبر الكرة الملعب بحركة أفقية لفترة طويلة أبدًا. ثم اضغط «تحقق».
جرّب بنفسك
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);
}
}
جميع دروس لعبة Unity: كاسر الطوب
تدرّب بنفسك: Playground لـ Unity