التبديل بين الحالات
جزء من قسم بناء ألعاب حقيقية في رحلة Unity على Coddy. الدرس 15 من 56.
تنفّذ كل حالة من حالات اللعبة عملاً مختلفًا في كل إطار. يضع switch على حقل الحالة هذا العمل في حالة منفصلة لكل حالة، وينفّذ كل إطار حالة واحدة بالضبط. يمر تغيير الحالة عبر طريقة واحدة، لذا تتطابق الشاشة دائمًا مع الحالة. تتضمن معركة الزعيم هذه مقدمةً، والقتال، وشاشةً للفوز:
public enum Phase { Intro, Fight, Won }
public class BossFight : MonoBehaviour
{
public GameObject introPanel;
public GameObject fightPanel;
public GameObject winPanel;
public int bossHp = 10;
private Phase phase;
private float timer = 3f;
void Start()
{
Enter(Phase.Intro);
}
void Update()
{
switch (phase)
{
case Phase.Intro:
timer -= Time.deltaTime;
if (timer <= 0f) Enter(Phase.Fight);
break;
case Phase.Fight:
if (bossHp <= 0) Enter(Phase.Won);
break;
case Phase.Won:
break;
}
}
void Enter(Phase next)
{
phase = next;
introPanel.SetActive(next == Phase.Intro);
fightPanel.SetActive(next == Phase.Fight);
winPanel.SetActive(next == Phase.Won);
}
}تنتهي كل حالة بـ break، لأن C# يرفض ترجمة حالة تستمر في تنفيذ الحالة التالية. عندما ينفد مؤقت المقدمة، يغيّر Enter(Phase.Fight) المرحلة، لكن حالة Fight لا تُنفّذ إلا في الإطار التالي، لأن هذا الإطار اختار حالته بالفعل. أما مع كتل if منفصلة متتابعة، فقد يبدأ الإطار القتال وينفّذ شيفرة القتال في الإطار نفسه.
Enter هو المكان الوحيد الذي يغيّر phase. تكون next == Phase.Fight مساويةً لـ true للوحة القتال فقط، لذا يُظهر استدعاء واحد تلك اللوحة ويخفي اللوحتين الأخريين. كذلك، يوضع العمل المرتبط بالدخول إلى حالة، مثل إعادة ضبط المؤقت، في Enter، ويُنفّذ مرة واحدة بدلًا من كل إطار.
التحدي
سهلسباق النقر: كم مرة يمكنك الضغط على Space خلال 5 ثوانٍ؟ يحتوي GameManager على تعداد GameState (Ready، Playing، GameOver)، ولوحة لكل حالة، ويستدعي Start الدالة SetState(GameState.Ready). اكتب Update وSetState.
في Update، استخدم switch على state:
- Ready: يبدأ Space جولة. لا تُحتسب هذه الضغطة كنقرة.
- Playing: تضيف كل ضغطة على Space العدد 1 إلى
taps، وتعرضه فيtapsTextعلى النحوTaps: 3. تنتهي اللعبة بعدroundTimeثانية (5). - GameOver: يعيد Space اللعبة إلى Ready.
تعيّن SetState(GameState next) قيمة state، وتعرض لوحة الحالة الجديدة فقط. عند الدخول إلى Playing، تبدأ جولة بـ 0 نقرة، وتظهر Taps: 0 على الشاشة، ويتبقى roundTime ثانية؛ وعند الدخول إلى GameOver، تعرض النتيجة في resultText على النحو Taps: 3.
اضغط تشغيل، وخض السباق مرتين، ثم اضغط تحقّق.
جرّب بنفسك
using UnityEngine;
using TMPro;
public enum GameState { Ready, Playing, GameOver }
public class GameManager : MonoBehaviour
{
public GameObject readyPanel;
public GameObject playPanel;
public GameObject gameOverPanel;
public TMP_Text tapsText;
public TMP_Text resultText;
public float roundTime = 5f;
public GameState state;
private int taps;
private float timeLeft;
void Start()
{
SetState(GameState.Ready);
}
void Update()
{
// بدّل حسب state:
// Ready: يبدأ Space جولة
// Playing: يسجّل Space ضغطة؛ وعندما ينتهي الوقت، تنتهي اللعبة
// GameOver: يعيد Space الحالة إلى Ready
}
void SetState(GameState next)
{
state = next;
// أظهر لوحة الحالة الجديدة فقط
// تبدأ جولة جديدة بـ 0 ضغطات ومدة roundTime ثانية؛ وفي النهاية، يعرض resultText عدد الضغطات
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس بناء ألعاب حقيقية
4المشاهد والمستويات
تحميل مشهدإعادة تشغيل المستوىالمستوى التاليالاحتفاظ بالبيانات بين المشاهدمراجعة: اختيار المستوى10مشروع: لعبة منصات ثلاثية الأبعاد
المسارالمنصات المتحركة2الأزرار والشاشات
الأزرار وonClickالتعبيرات Lambdaالربط في Inspectorتشغيل اللوحات وإيقافهاأشرطة الصحةمراجعة: متجر الترقيات5الحفظ باستخدام PlayerPrefs
حفظ رقمالتحميل بقيمة افتراضيةأعلى نتيجةحفظ الإعداداتمراجعة: العملات في البنك6مشروع: عدّاء بلا نهاية
ثلاثة مساراتعوائق أمامك