Menu
CoddyTech

الانتقالات

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

من يقرر متى تتغير الحالة؟ إن جعل المالك يقرر ذلك يعيد جميع القواعد إلى تحديث واحد، كما فعلت عبارة التبديل. والإجابة المعتادة هي أن كل حالة تعرف طريقها للخروج: ففي دالة Tick الخاصة بها، تتحقق من شرطها وتطلب من الآلة الانتقال إلى الحالة التالية. تنتظر هذه القنبلة حتى يقترب اللاعب، ثم تحرق فتيلها، وتعود إلى الانتظار إذا ابتعد اللاعب راكضًا:

public class Bomb : MonoBehaviour
{
    public Transform player;
    public StateMachine machine = new StateMachine();
    public IState idle;
    public IState fuse;

    void Start()
    {
        idle = new IdleState(this);
        fuse = new FuseState(this);
        machine.ChangeState(idle);
    }

    void Update() { machine.Tick(); }

    public bool PlayerNear()
    {
        return Vector3.Distance(transform.position, player.position) < 3f;
    }
}

public class IdleState : IState
{
    private Bomb bomb;
    public IdleState(Bomb bomb) { this.bomb = bomb; }

    public void Enter() { }
    public void Exit() { }

    public void Tick()
    {
        if (bomb.PlayerNear()) bomb.machine.ChangeState(bomb.fuse);
    }
}

public class FuseState : IState
{
    private Bomb bomb;
    private float timer;
    public FuseState(Bomb bomb) { this.bomb = bomb; }

    public void Enter() { timer = 2f; }
    public void Exit() { }

    public void Tick()
    {
        if (!bomb.PlayerNear())
        {
            bomb.machine.ChangeState(bomb.idle);
            return;
        }
        timer -= Time.deltaTime;
        if (timer <= 0f)
        {
            Debug.Log("Boom!");
            Object.Destroy(bomb.gameObject);
        }
    }
}

تحصل كل حالة على القنبلة في مُنشئها، وتصل من خلالها إلى الآلة واختبار اقتراب اللاعب والحالات الأخرى. تنشئ القنبلة كل حالة مرة واحدة في Start، لذا لا تنشئ الحالة حالةً أخرى باستخدام new: فالحالتان اللتان تنشئ كل منهما الأخرى في مُنشئهما ستدخلان في حلقة إلى أن يفيض المكدس. لا تفعل دالة Update الخاصة بالقنبلة سوى تحديث الآلة، وتوجد القواعد في الحالات التي تخصها: فتيل FuseState الذي مدته ثانيتان هو مسؤولية FuseState وحدها.

تشغّل ChangeState دالتي Exit في FuseState وEnter في IdleState مباشرةً، لكن بقية دالة Tick في FuseState ستظل تعمل بعد استدعاء الدالة. يوقفها return، وإلا لاحترق الفتيل إطارًا إضافيًا رغم أن الحالة انتهت بالفعل. تُكتب Destroy على النحو Object.Destroy: ترثها MonoBehaviour من فئة Object في Unity، أما الفئة العادية فعليها ذكر اسم الفئة.

challenge icon

التحدي

متوسط

اكتب انتقالات مصيدة الذباب في كل استدعاء لـ Tick في FlytrapStates.cs.

  1. مفتوحة: عندما يتحقق trap.PlayerInReach()، استدعِ trap.machine.ChangeState(trap.snap);.
  2. انقضاض: أضف Time.deltaTime إلى timer؛ وعند 0.5، انتقل إلى trap.chew إذا كان اللاعب لا يزال في المتناول، وإلا فانتقل إلى trap.open.
  3. مضغ: أنقص timer بدءًا من 3؛ وعند 0، انتقل إلى trap.open.

اضغط «العب»، وامشِ نحو المصيدة، ثم تفادَها. بعد ذلك اضغط «تحقق».

جرّب بنفسك

using UnityEngine;

public class OpenState : IState
{
    private Flytrap trap;

    public OpenState(Flytrap trap)
    {
        this.trap = trap;
    }

    public void Enter()
    {
        trap.Paint(new Color(0.3f, 0.8f, 0.2f));
    }

    public void Tick()
    {
        // انطبق عندما يصبح اللاعب في المتناول
    }

    public void Exit()
    {
    }
}

public class SnapState : IState
{
    private Flytrap trap;
    private float timer;

    public SnapState(Flytrap trap)
    {
        this.trap = trap;
    }

    public void Enter()
    {
        timer = 0f;
        trap.Paint(new Color(1f, 0.55f, 0.1f));
    }

    public void Tick()
    {
        // بعد 0.5 ثانية: امضغ إذا كان اللاعب لا يزال في المتناول، وإلا فانفتح مجددًا
    }

    public void Exit()
    {
    }
}

public class ChewState : IState
{
    private Flytrap trap;
    private float timer;

    public ChewState(Flytrap trap)
    {
        this.trap = trap;
    }

    public void Enter()
    {
        timer = 3f;
        trap.Paint(new Color(0.5f, 0.05f, 0.1f));
        Debug.Log("Chomp!");
    }

    public void Tick()
    {
        // بعد 3 ثوانٍ: انفتح مجددًا
    }

    public void Exit()
    {
    }
}

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

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