כוונה בעזרת המשוט
שיעור 4 מתוך 16 בקורס משחק Unity: שובר לבנים של Coddy.
בקפיצה מושלמת השחקן לא יכול לכוון: הכדור עוזב את המשטח בזווית שבה הגיע אליו. במשחקי Brick Breaker המשטח הוא שקובע את הכיוון. פגיעה סמוך לקצה השמאלי שולחת את הכדור למעלה ולשמאלה, פגיעה באמצע שולחת אותו ישר למעלה, וככל שהפגיעה רחוקה יותר מהאמצע, כך הזווית רחבה יותר.
המירו את מיקום הפגיעה למספר שבין -1 בקצה השמאלי ל־1 בקצה הימני: היסט ה־x של הכדור ממרכז המשטח, מחולק במחצית רוחב המשטח. נניח שרוחב המשטח הוא 4 יחידות, המרכז שלו נמצא ב־x = 2, והכדור פוגע ב־x = 3. ההיסט הוא 1, מחצית הרוחב היא 2, ולכן המספר הוא 0.5, והכיוון החדש הוא 0.5 לרוחב ו־1 למעלה, כלומר (0.5, 1, 0), מנורמל. פגיעה בדיוק בקצה נותנת 1 או -1, כלומר זווית של 45 מעלות ביחס לכיוון ישר למעלה. הגבילו את המספר לטווח הזה, כי הכדור יכול לגעת בפינת המשטח מעט מעבר לקצה.
הפונקציה OnCollisionEnter של הכדור פועלת לאחר שהפיזיקה חישבה את הקפיצה, ולכן מהירות שמגדירים שם מחליפה אותה. הקירות שולחים את אותה הודעה, ועליהם לשמור על הקפיצה הרגילה שלהם, ולכן קודם בדקו במה הייתה הפגיעה. collision.collider.bounds הוא התיבה שהמתנגש תופס בעולם, כולל קנה המידה:
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);
}אתגר
קלהוסף את OnCollisionEnter(Collision collision) אל Ball:
- אל תעשה דבר אלא אם האובייקט שנפגע מתויג כ-
Paddle. - חשב את
x: ערך ה-x של הכדור פחות ערך ה-x של המחבט, חלקי חצי מרוחב המחבט (collision.collider.bounds.size.x), כשהתוצאה מוגבלת לטווח שבין -1 ל-1. - הגדר את המהירות של Rigidbody ל-
new Vector3(x, 1f, 0f), מנורמל, כפול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;
}
void FixedUpdate()
{
if (!launched) return;
rb.linearVelocity = rb.linearVelocity.normalized * speed;
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.