מאגר עם תור
חלק מהיחידה ארכיטקטורת משחקים ב-Unity במסלול ה-Unity של Coddy. שיעור 38 מתוך 50.
בריכה צריכה מקום לשמור בו את העצמים העודפים שלה, ול־C# יש אוסף שמתאים לכך, Queue<T>: Enqueue מוסיפה פריט לסוף, Dequeue לוקחת את הפריט שבתחילת התור, ו־Count מציינת כמה פריטים ממתינים. האקווריום הזה מעלה בועה כל 0.3 שניות, וכל בועה חוזרת לבריכה כשהיא מגיעה לפני המים:
using System.Collections.Generic;
using UnityEngine;
public class BubblePool : MonoBehaviour
{
public GameObject bubblePrefab;
private Queue<GameObject> pool = new Queue<GameObject>();
private float timer;
void Update()
{
timer += Time.deltaTime;
if (timer >= 0.3f)
{
timer = 0f;
Get(new Vector3(Random.Range(-2f, 2f), 0f, 0f));
}
}
public GameObject Get(Vector3 position)
{
GameObject bubble;
if (pool.Count > 0)
{
bubble = pool.Dequeue();
}
else
{
bubble = Instantiate(bubblePrefab);
bubble.GetComponent<Bubble>().pool = this;
}
bubble.transform.position = position;
bubble.SetActive(true);
return bubble;
}
public void Return(GameObject bubble)
{
bubble.SetActive(false);
pool.Enqueue(bubble);
}
}// Bubble.cs, על ה-prefab של הבועה
public BubblePool pool;
void Update()
{
transform.Translate(0f, 2f * Time.deltaTime, 0f);
if (transform.position.y > 5f) pool.Return(gameObject);
}Get בודקת קודם את Count, משום שקריאה ל־Dequeue כשהתור ריק זורקת חריגת InvalidOperationException. רק אז היא קוראת ל־Instantiate, ורק לבועה חדשה צריך להגדיר את השדה pool שלה: לבועה שנעשה בה שימוש חוזר הוא כבר מוגדר. התור מוסר תחילה את הבועה שהמתינה הכי הרבה זמן — הראשון שנכנס הוא הראשון שיוצא. בועה שמגיעה לפני המים קוראת ל־Return במקום ל־Destroy, ונשארת בסצנה כשהיא לא פעילה עד לקריאה הבאה ל־Get.
Get מציבה את הבועה לפני SetActive(true), מפני שהפעלתה מריצה מיד את OnEnable, וכל קוד שנמצא שם צריך לראות את המיקום החדש, ולא את המקום שבו הבועה נעלמה בפעם הקודמת. זו גם הנקודה שבה אובייקט שנעשה בו שימוש חוזר מתחיל מחדש: Awake ו־Start רצו פעם אחת, כשהבועה נוצרה, ו־OnEnable רצה בכל קריאה ל־Get.
אתגר
בינוניעקבות בחול. החצים מזיזים את השחקן (מוכן). Trail.cs, שמוצמד לשחקן, משאיר עקבת רגל בכל יחידת מרחק של 1 שהשחקן הולך, באמצעות קריאה ל־Get(position), וכל Footprint נשארת למשך life (1.5) שניות. כיום Get יוצר עקבת רגל חדשה בכל פעם, וכל אחת משמידה את עצמה. נשתמש בבריכה:
- ב־
Trail.cs, שמור את עקבות הרגל העודפות בתוךQueue<GameObject>. צריך להגדיר את שדהtrailשל כל עקבת רגל שה־Trail יוצר כך שיפנה ל־Trail הזה. - ב־Start, מלא את הבריכה ב־
prewarm(6) עקבות רגל, שנוצרות ומכובות, כדי שהצעדים הראשונים לא ייצרו עקבות חדשות. Get(position)לוקחת עקבת רגל מהתור אם יש בו אחת, ויוצרת חדשה רק כשהוא ריק; לאחר מכן היא מציבה את עקבת הרגל ומדליקה אותה.Return(footprint)מכבה את עקבת הרגל ומכניסה אותה לתור.- ב־
Footprint.cs, עקבת רגל סופרת את גילה, ואחריlifeשניות חוזרת באמצעותtrail.Return(gameObject)במקום להיהרס. עקבת רגל שנעשה בה שימוש חוזר נשארת למשך 1.5 שניות מלאות שוב.
לחץ על Play, הסתובב קצת ואז לחץ על Check.
נסו בעצמכם
using System.Collections.Generic;
using UnityEngine;
public class Trail : MonoBehaviour
{
public GameObject footprintPrefab;
public float step = 1f;
public int prewarm = 6;
private Vector3 lastDrop;
void Start()
{
lastDrop = transform.position;
// מלא את המאגר בעקבות רגליים שהוכנו מראש
}
void Update()
{
if (Vector3.Distance(transform.position, lastDrop) >= step)
{
lastDrop = transform.position;
Get(new Vector3(transform.position.x, 0.02f, transform.position.z));
}
}
public GameObject Get(Vector3 position)
{
GameObject footprint = Instantiate(footprintPrefab, position, Quaternion.identity);
footprint.GetComponent<Footprint>().trail = this;
return footprint;
}
public void Return(GameObject footprint)
{
// עקבות רגליים רזרביות ממתינות במאגר
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.