Menu
CoddyTech

الاحتفاظ بالبيانات بين المشاهد

جزء من قسم إنشاء ألعاب حقيقية في رحلة Unity على Coddy. الدرس 20 من 60.

يؤدي تحميل مشهد إلى تدمير كل كائن في المشهد القديم، لكن بعض الأشياء يجب أن تستمر طوال اللعبة، مثل العملات التي يحملها اللاعب من مستوى إلى آخر. تنقل DontDestroyOnLoad(gameObject) كائنًا من مشهده إلى مشهد خاص به، يُسمى DontDestroyOnLoad في التسلسل الهرمي عند الضغط على «العب»، ولا تؤثر فيه عمليات التحميل. تعمل هذه الطريقة على كائن جذري فقط: أما إذا استُخدمت على كائن فرعي، فسيسجل Unity تحذيرًا ولن يُبقي أي شيء. تأتي الكائنات الفرعية للكائن الذي تم الاحتفاظ به معه، لكن الكائنات التي لا يشير إليها إلا فلا: بعد التحميل، سيحتوي الحقل الذي كان يشير إلى كائن من المشهد القديم على كائن مدمّر، وتكون نتيجة مقارنته مع null هي التساوي.

public class GameSession : MonoBehaviour
{
    public static GameSession Instance;
    public int coins;

    void Awake()
    {
        if (Instance != null)
        {
            Destroy(gameObject);
            return;
        }
        Instance = this;
        DontDestroyOnLoad(gameObject);
    }
}

يوجد GameSession هذا في مشهد Menu. ينتقل اللعب من Menu إلى Level1 ثم يعود إلى Menu، ويعيد مشهد Menu إنشاء جميع كائناته، بما فيها GameSession جديد، بينما لا يزال الكائن المحتفَظ به موجودًا. من دون التحقق في Awake، سيكون هناك كائنان، وسيتولى الكائن الجديد التحكم في Instance مع 0 عملة. أما بوجوده، فيجد الكائن الجديد أن Instance معيّن بالفعل، فيدمّر نفسه ويتوقف، وتبقى الجلسة التي اجتازت المستويات.

إن return مهم لأن Destroy ينتظر حتى نهاية الإطار. ومن دونه، سيظل باقي Awake يعمل للكائن الجديد: إذ ستجعل Instance = this; كل سكربت يشير إلى كائن على وشك التدمير.

challenge icon

التحدي

سهل

أبقِ ساعة تشغيل واحدة مستمرة عبر تحميل كل مشهد.

  1. في Awake()، إذا كان Instance != null، فاستدعِ Destroy(gameObject); ثم return;. وإلا، فعيّن Instance واستدعِ DontDestroyOnLoad(gameObject);.
  2. يؤدي التحميل إلى إتلاف نص المستوى القديم، لذا في Update()، قبل سطر النص، عندما يكون clockText == null، عيّن clockText = GameObject.Find("ClockText").GetComponent<TMP_Text>();.

اضغط «العب»، وانتقل إلى Level2 ثم عُد: ستواصل ساعة واحدة العدّ. ثم اضغط «تحقق».

جرّب بنفسك

using UnityEngine;
using TMPro;

public class RunClock : MonoBehaviour
{
    public static RunClock Instance;
    public TMP_Text clockText;
    private float seconds;

    void Awake()
    {
        Instance = this;
    }

    void Update()
    {
        seconds += Time.deltaTime;
        clockText.text = "Time: " + seconds.ToString("0.0");
    }

    public void Split()
    {
        Debug.Log("Split: " + seconds.ToString("0.0"));
    }
}

جميع دروس إنشاء ألعاب حقيقية

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