الحالات كأصناف
جزء من قسم هندسة الألعاب في Unity في رحلة Unity على Coddy. الدرس 35 من 64.
يجمع مفتاح Section 3 المبني على تعداد عمل كل حالة في دالة Update واحدة. لكن هذا النهج لا يتوسع عندما تصبح لكل حالة بياناتها الخاصة: إذ ينتهي المطاف بمؤقت لا تستخدمه سوى حالة واحدة بوصفه حقلًا في MonoBehaviour، إلى جانب حقول كل الحالات الأخرى، ويجب أن تتذكر كل حالة في case إعادة ضبط ما تستخدمه. يمنح نمط الحالة في C# كل حالة صفًا خاصًا بها، وتطبّق كل الفئات واجهة واحدة. يومض هذا المنارة أو يبقى مضاءً، ويبدّل Space بين الحالتين:
public interface IState
{
void Enter();
void Tick();
void Exit();
}
public class BlinkState : IState
{
private Renderer lamp;
private float timer;
public BlinkState(Renderer lamp)
{
this.lamp = lamp;
}
public void Enter() { timer = 0f; }
public void Tick()
{
timer += Time.deltaTime;
if (timer >= 0.5f)
{
timer = 0f;
lamp.enabled = !lamp.enabled;
}
}
public void Exit() { lamp.enabled = true; }
}
public class SteadyState : IState
{
public void Enter() { }
public void Tick() { }
public void Exit() { }
}
public class Beacon : MonoBehaviour
{
public Renderer lamp;
private IState blink;
private IState steady;
private IState current;
void Start()
{
blink = new BlinkState(lamp);
steady = new SteadyState();
SetState(steady);
}
void Update()
{
if (Keyboard.current.spaceKey.wasPressedThisFrame) SetState(current == steady ? blink : steady);
current.Tick();
}
void SetState(IState next)
{
if (current != null) current.Exit();
current = next;
current.Enter();
}
}الحالات فئات C# عادية، وليست MonoBehaviours. تنشئها باستخدام new وتمرر إليها ما تحتاجه عبر المُنشئ، وهنا هو Renderer الخاص بالمصباح، لأنها ليست مكوّنات ولا يمكنها استدعاء GetComponent أو عرض حقول في Inspector. ولا تستدعي Unity دوالها أيضًا: فـ Beacon هو MonoBehaviour، لذا تستدعي دالة Update الخاصة به current.Tick() في كل إطار.
ينتمي timer إلى BlinkState وحدها، وتضبطه Enter على 0 في كل مرة تبدأ فيها المنارة بالوميض. تنظّف Exit الحالة عند انتهائها: قد يُضغط Space بينما يكون المصباح مطفأً، فتُعيده Exit إلى الإضاءة، وبالتالي لا تبدأ SteadyState ومصباحها مطفأ. تنفّذ SetState دالة Exit للحالة القديمة، ثم دالة Enter للحالة الجديدة. أما الحالة الثالثة، مثل النبض البطيء، فتكون فئة إضافية، ولا يتغير Update الخاص بـ Beacon.
التحدي
متوسطاكتب حالة المسح للبرج.
- في
IState.cs، أعلنpublic interface IStateمعvoid Enter();وvoid Tick();وvoid Exit();. - في
TurretStates.cs، اكتبScanState : IState، مع تمرير الرأس إليه. عند الدخول: اجعل الزاوية 0، ولون الرأسColor.green. عند التحديث: حرّك زاوية y المحلية للرأس بين-45و45، بمعدل90درجة في الثانية. Turret: أدخِل حالة واحدة في Start، وحدّثها في Update.
اضغط على «العب»: سيتحرك الرأس الأخضر ذهابًا وإيابًا. ثم اضغط على «تحقق».
جرّب بنفسك
using UnityEngine;
// ScanState
جميع دروس هندسة الألعاب في Unity
1المكوّنات، لا التسلسلات الهرمية
مكوّنات صغيرةنص برمجي أساسي للعدومكوّنات مجرّدةالمكوّنات تعمل معًامراجعة: برج معياريمراجعة: مدفع مزدوج4البيانات المُسلسلة
الأصناف القابلة للتسلسلالقوائم في Inspectorالتعدادات في Inspectorمراجعة: جدول الغنائممراجعة: اختيار الغنائم عشوائيًا7آلات الحالات
الحالات كأصنافحالة التنبيهآلة حالاتالانتقالاتعقول الأعداءالفارس يهاجممراجعة: حالات الباب2الواجهات في Unity
IDamageableالواجهات وTryGetComponentGetComponentsمراجعة: مفتاح التفاعلمراجعة: أقرب عنصر ضمن النطاقتدرّب بنفسك: Playground لـ Unity