Menu
CoddyTech

מכונת מצבים

חלק מהיחידה ארכיטקטורת משחקים ב-Unity במסלול ה-Unity של Coddy. שיעור 29 מתוך 50.

השיטה SetState של המגדלור תהיה זהה בכל אובייקט שיש לו מצבים: צריח, אויב, דלת. הקוד הזה יכול להיות במחלקה משלו, מכונת מצבים, שמחזיקה את המצב הנוכחי ומשנה אותו. כל אובייקט יוצר מכונה אחת וקורא לה, במקום לחזור על הקוד:

public class StateMachine
{
    public IState Current { get; private set; }

    public void ChangeState(IState next)
    {
        Current?.Exit();
        Current = next;
        Current.Enter();
    }

    public void Tick()
    {
        Current?.Tick();
    }
}

public class Beacon : MonoBehaviour
{
    public Renderer lamp;
    private StateMachine machine = new StateMachine();
    private IState blink;
    private IState steady;

    void Start()
    {
        blink = new BlinkState(lamp);
        steady = new SteadyState();
        machine.ChangeState(steady);
    }

    void Update()
    {
        if (Keyboard.current.spaceKey.wasPressedThisFrame) machine.ChangeState(machine.Current == steady ? blink : steady);
        machine.Tick();
    }
}

לקריאה הראשונה ל־ChangeState אין מצב לעזוב: Current הוא null, ו־?. מדלג על הקריאה ל־Exit. יחידה 1 הזהירה ש־?. לא מזהה את ה־null המדומה של Unity; זה קשור לאובייקטים של Unity שהושמדו, והמצבים הם אובייקטי C# רגילים, לכן ?. בטוח כאן. ל־Current יש private set, ולכן שום סקריפט לא יכול להחליף את המצב בלי לעבור דרך ChangeState וה־Exit וה־Enter שלה.

הסדר בתוך ChangeState חשוב בכל פעם ששני מצבים נוגעים באותו הדבר. Exit מבטל את מה שהמצב הישן שינה, ואז Enter מגדיר את המצב החדש, כך שלמצב החדש יש את המילה האחרונה. אם Enter של DarkState היה מכבה את המנורה ופועל לפני Exit של BlinkState, אותו Exit היה מדליק מחדש את המנורה במצב החשוך. גם StateMachine היא מחלקה רגילה: המגדלור, צריח ואויב יוצרים כל אחד מכונה משלו עם new וקוראים ל־Tick שלה מתוך Update שלהם.

challenge icon

אתגר

בינוני

החזק את Space כדי להתגנב. WalkState ו-SneakState מוכנים ב-PlayerStates.cs: המתודות Enter ו-Exit שלהן מתעדות מה קורה (Walk: enter, Sneak: exit...), והמתודה Tick שלהן קוראת ל-Move() של השחקן. כתוב את המכונה שמפעילה אותן.

  • ב-StateMachine.cs, כתוב מחלקה רגילה StateMachine עם מאפיין ציבורי Current שרק המכונה יכולה להגדיר, מתודה ChangeState(IState next) שמפעילה את Exit של המצב הישן ואז את Enter של המצב החדש, ומתודה Tick() שמפעילה את Tick של המצב הנוכחי.
  • השחקן מבקש את המצב שלו בכל פריים, לכן קריאה ל-ChangeState עם המצב שכבר נוכחי לא עושה כלום: אין Exit ואין Enter.
  • ב-Player.cs, הוסף שדה מסוג StateMachine בשם machine. ב-Start, צור את המכונה ואת שני המצבים (כל אחד מקבל את השחקן) והתחל בהליכה. ב-Update, עבור להתגנבות בזמן שמחזיקים את Space, ולהליכה אחרת כך, ואז בצע tick למכונה.

לחץ על Play, לך, החזק את Space והמשך ללכת, ואז לחץ על Check.

נסו בעצמכם

// StateMachine: Current, ChangeState ו-Tick
quiz iconבחנו את עצמכם

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

כל השיעורים ביחידה ארכיטקטורת משחקים ב-Unity