סינגלטון גנרי
חלק מהיחידה ארכיטקטורת משחקים ב-Unity במסלול ה-Unity של Coddy. שיעור 34 מתוך 50.
היחידה השלישית מציגה singleton בן חמש שורות שכל מנהל חוזר עליהן: Instance סטטי, Awake שמגדירה אותו ובדיקת כפילות. מחלקת בסיס גנרית כותבת אותן פעם אחת. כל מנהל יורש ממנה ומציין את שמו כסוג:
public abstract class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
public static T Instance { get; private set; }
protected virtual void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this as T;
}
}
public class ScoreManager : Singleton<ScoreManager>
{
public int score;
public void Add(int points) { score += points; }
}
public class SoundManager : Singleton<SoundManager>
{
public void Play(string clip) { Debug.Log("Playing " + clip); }
}// בכל סקריפט
ScoreManager.Instance.Add(10);
SoundManager.Instance.Play("coin");חבר סטטי במחלקה גנרית שייך לכל סוג שנוצר ממנה: Singleton<ScoreManager> ו-Singleton<SoundManager> הם שני סוגים, שלכל אחד מהם יש Instance משלו, כך שהמנהלים אף פעם לא חולקים אותו. ScoreManager.Instance כבר מוגדר כ-ScoreManager, ולשם כך נועד T. בתוך מחלקת הבסיס, this מוכר רק כ-Singleton<T>, ולכן this as T מעביר אותו בתור המנהל שהוא באמת.
מחלקת הבסיס היא אבסטרקטית: Unity מציבה על אובייקטים רק את המנהלים. מנהל שזקוק ל-Awake משלו לא צריך לכתוב void Awake() רגיל. פעולה זו מסתירה את המתודה של מחלקת הבסיס (המהדר מזהיר על כך), Unity קוראת רק למתודה של המנהל, ו-Instance לעולם לא מוגדר. יש לדרוס אותה ולקרוא קודם למתודה של מחלקת הבסיס:
protected override void Awake()
{
base.Awake();
score = 0;
}אתגר
בינוניעיירה ויער, המחוברים בפורטלים סגולים. בכל סצנה יש אובייקט Wallet ואובייקט MusicPlayer משלה, כך שכל אחד מהם מתנגן בפני עצמו, והמטבעות קוראים ל־Wallet.Instance.Add(1). כיום כל מנהל הוא הסינגלטון של יחידה 3, ולכן כל טעינה מחליפה את הארנק בארנק ריק. תנו לשני המנהלים מחלקת בסיס גנרית שתשאיר אותם לאורך טעינות של סצנות:
- ב־
PersistentSingleton.cs, כתבוpublic abstract class PersistentSingleton<T>, מחלקה שיורשת מ־MonoBehaviour עבור כל טיפוס T שיורש מ־MonoBehaviour, עםInstanceסטטי ציבורי מטיפוס T שרק המחלקה יכולה להגדיר, ועםprotected virtual void Awake(). - ה־Awake שלה משאיר את הראשון מסוגו: הוא הופך ל־Instance ושורד טעינות של סצנות. כל אחד שמופיע אחריו משמיד את האובייקט שלו עצמו ואינו משנה דבר.
Walletו־MusicPlayerיורשים ממנה, והשדותInstanceשלהם עצמם מוסרים.- ל־
MusicPlayerנשאר Awake משלו שרושם ביומןNow playing: Adventure. הוא חייב לרוץ אחרי ה־Awake של מחלקת הבסיס, ורק עבור זה שנשאר, כך שהמוזיקה תתחיל פעם אחת בכל משחק.
החצים מזיזים את Player. לחצו על Play, אספו את המטבע, עברו ליער וחזרו, ואז לחצו על Check.
נסו בעצמכם
using UnityEngine;
// PersistentSingleton<T>: מופע יחיד שנשמר גם בעת טעינת סצנות
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה ארכיטקטורת משחקים ב-Unity
1רכיבים, לא היררכיות
רכיבים קטניםסקריפט בסיס לאויברכיבים מופשטיםרכיבים שעובדים יחדסיכום: צריח מודולרי