Menu
CoddyTech

ריבוי כדורים

שיעור 15 מתוך 16 בקורס משחק Unity: שובר לבנים של Coddy.

שדרוג Multiball מפצל את הכדור: שני עותקים עפים מהמקום שבו הוא נמצא. Instantiate מעתיק אובייקט מהסצנה כפי שהוא מעתיק prefab, אבל רק מה שה־Inspector היה שומר עובר: שדות ציבוריים ושדות עם [SerializeField], כמו speed ו־paddle. שדה פרטי כמו launched מתחיל בערך ברירת המחדל שלו, false, והמהירות של ה־Rigidbody מתחילה באפס. לכן צריך לומר לעותק מה לעשות, אחרת הוא נצמד למשוט.

כשיש כמה כדורים במשחק, ה־GameManager שומר אותם בתוך List<Ball>, וכדור שאבד גורם לאובדן חיים רק כשהוא האחרון. סליימים שמתפצלים פועלים באותו אופן:

List<Slime> slimes = new List<Slime>();

public void Split(Slime slime)
{
    Slime half = Instantiate(slime, slime.transform.position, Quaternion.identity);
    half.Hop(Vector3.left);   // השדות הפרטיים של העותק מאותחלים מחדש: צריך להורות לו מה לעשות
    slimes.Add(half);
}

public void SlimeDied(Slime slime)
{
    slimes.Remove(slime);
    Destroy(slime.gameObject);
    if (slimes.Count == 0) Debug.Log("Room cleared");
}

הכדור הראשון ברשימה עשוי להיות עותק, מכיוון שהמקורי יכול ללכת לאיבוד בזמן שהעותקים ממשיכים לעוף, ולכן קוד שזקוק לכדור משתמש ברשימה ולא בשדה Ball מהסצנה.

challenge icon

אתגר

קשה
  1. ב־GameManager, הוסף using System.Collections.Generic; ואת List<Ball> balls = new List<Ball>();. הפונקציה Start() מוסיפה אליו תחילה את ball.
  2. כתוב public void SplitBall(): צור שני עותקים של balls[0] במיקום שלו, אחד שמשוגר לכיוון new Vector3(-0.6f, 1f, 0f) ואחד לכיוון new Vector3(0.6f, 1f, 0f), והוסף את שניהם לרשימה.
  3. שנה את BallLost: כשיש יותר מכדור אחד ברשימה, הסר ממנה את הכדור שאבד והשמד אותו, מבלי לאבד חיים. כשמסיימים שלב, החזר את balls[0] אל המחבט במקום את ball.
  4. ב־PowerUp, פריט Multiball קורא ל־GameManager.Instance.SplitBall() כשאוספים אותו.

לחץ על Play, תפוס פריט כוח ורוד, ואז לחץ על Check.

נסו בעצמכם

using UnityEngine;
using UnityEngine.SceneManagement;
using TMPro;

public class GameManager : MonoBehaviour
{
    public static GameManager Instance;

    public Brick brickPrefab;
    public Transform wall;
    public string[] levels;
    public float spacingX = 1.75f;
    public float spacingY = 0.75f;
    public float topY = 6f;

    public Ball ball;
    public int lives = 3;
    public TMP_Text scoreText;
    public TMP_Text livesText;
    public GameObject gameOverPanel;
    public GameObject[] powerUps;
    public float dropChance = 0.15f;

    int score;
    int level;
    int bricksLeft;

    void Awake()
    {
        Instance = this;
    }

    void Start()
    {
        BuildLevel(0);
        ShowHud();
    }

    void BuildLevel(int index)
    {
        level = index;
        string[] rows = levels[index].Split('/');
        for (int row = 0; row < rows.Length; row++)
        {
            string line = rows[row];
            float left = -(line.Length - 1) * spacingX / 2f;
            for (int col = 0; col < line.Length; col++)
            {
                char c = line[col];
                if (c == '.') continue;
                Vector3 pos = new Vector3(left + col * spacingX, topY - row * spacingY, 0f);
                Brick brick = Instantiate(brickPrefab, pos, Quaternion.identity, wall);
                brick.SetHits(c - '0');
                bricksLeft++;
            }
        }
    }

    public void BrickBroken(Brick brick)
    {
        score += brick.points;
        bricksLeft--;
        ShowHud();
        if (Random.value < dropChance)
        {
            GameObject prefab = powerUps[Random.Range(0, powerUps.Length)];
            Instantiate(prefab, brick.transform.position, Quaternion.identity);
        }
        if (bricksLeft == 0)
        {
            ball.ResetToPaddle();
            BuildLevel((level + 1) % levels.Length);
        }
    }

    public void BallLost(Ball lost)
    {
        lives--;
        ShowHud();
        if (lives == 0)
        {
            gameOverPanel.SetActive(true);
            lost.gameObject.SetActive(false);
        }
        else lost.ResetToPaddle();
    }

    public void PlayAgain()
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
    }

    void ShowHud()
    {
        scoreText.text = "Score: " + score;
        livesText.text = "Lives: " + lives;
    }
}
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה משחק Unity: שובר לבנים