Menu
CoddyTech

آلة حالات

جزء من قسم هندسة الألعاب في Unity في رحلة Unity على Coddy. الدرس 37 من 64.

ستكون طريقة 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

التحدي

متوسط

شغّل حالات جاهزية اللاعب باستخدام آلة.

  1. في StateMachine.cs، اكتب public class StateMachine مع public IState Current { get; private set; } وTick() تستدعي دورتها.
  2. تتجاهل ChangeState(IState next) الحالة الحالية؛ وإلا تستدعي Exit، وتعيّن Current، ثم تستدعي Enter.
  3. Player: تنشئ Start كلاً من machine وwalk وsneak، وتبدأ بالمشي؛ وتتحرك Update خلسةً ما دام مفتاح المسافة مضغوطًا، وإلا تمشي، ثم تستدعي الدورة.

اضغط «العب» واستمر في الضغط على مفتاح المسافة: Sneak: enter. ثم اضغط «تحقق».

جرّب بنفسك

// StateMachine: ‏Current وChangeState وTick

جميع دروس هندسة الألعاب في Unity

تدرّب بنفسك: Playground لـ Unity