الوحدة: التعرف على الأشياء القابلة للكتابة

الصورة

في هذا البرنامج التعليمي ، ستتعلم كيفية إنشاء واستخدام كائنات قابلة للبرمجة في الوحدة. يمكن أن تساعد الكائنات القابلة للبرمجة في تحسين سير عملك ، وتقليل بصمة الذاكرة ، وحتى السماح لك بتقسيم بنية التعليمات البرمجية.

وفقًا لوثائق الوحدة ، ScriptableObject هو رمز فئة يسمح لك بإنشاء كائنات قابلة للكتابة في اللعبة لتخزين كميات كبيرة من البيانات المشتركة التي تكون مستقلة عن مثيلات البرنامج النصي.

هناك العديد من الأسباب لاستخدام الكائنات القابلة للبرمجة في الوحدة. يمكنهم تقليل حجم الذاكرة المستخدمة لكل إعداد إضافي إضافي ، لأن الكائن القابل للبرمجة يتبع بشكل أساسي نمط تصميم Flyweight .

ميزة أخرى للكائنات القابلة للبرمجة ، والتي ستكون الموضوع الرئيسي لهذا البرنامج التعليمي ، هي استخدامها لنقل البيانات بشكل ملائم. سننظر في هذه الخاصية كمثال على إنشاء متجر تجار السيف ، والذي سيعرض المعلمات والأسعار والأوصاف لمختلف السيوف.

ملاحظة: يفترض هذا البرنامج التعليمي أنك معتاد على محرر الوحدة. يجب أن تفهم كيفية تحرير التعليمات البرمجية في محرر التعليمات البرمجية والحصول على المعرفة الأساسية لـ C #. إذا كنت بحاجة إلى تحسين مهارات Unity الخاصة بك ، فراجع دروس Unity الأخرى.

للوصول إلى العمل


لنبدأ بتنزيل المواد التي نحتاجها.

قم بفك ضغط الملف الذي تم تنزيله في مكان مناسب لك وافتح مشروع Scriptable Object Tutorial-Starter في الوحدة.

يجب أن ترى المجلد التالي الذي تم إنشاؤه كجزء من شراء المشروع:


  • _Setup : في هذا البرنامج التعليمي ، هذا المجلد غير مطلوب.
  • المشاهد : يحتوي على مشهد تاجر السيف الذي سنقوم بتغطيته طوال البرنامج التعليمي. افتح هذا المشهد.
  • النصوص : حتى الآن لا يوجد سوى نص واحد ، ولكن خلال البرنامج التعليمي سنقوم بإنشاء نصوص جديدة.
  • أيقونات السيف : تحتوي على صور ثابتة للسيوف الفردية.
  • Sword Prefabs : يحتوي على الجاهزة لجميع السيوف في مشهد Sword Merchant.

إنشاء كائن قابل للبرمجة


للبدء ، انتقل إلى مشهد Sword Merchant . يجب أن يبدو مثل هذا:


تحضير كائن قابل للبرمجة


حان الوقت لإنشاء أول كائن قابل للبرمجة!

في مجلد البرامج النصية ، قم بإنشاء برنامج نصي جديد يسمى SwordData . سيتم استخدام هذه الفئة كحاوية لجميع بيانات السيف المعروضة في متجر تاجر السيف.

داخل هذه الفئة ، ابدأ MonoBehaviour من MonoBehaviour بدلاً من MonoBehaviour :

 public class SwordData : ScriptableObject { } 

يخبر هذا الإجراء Unity أننا ما زلنا نريد استخدام ميزات وأساليب Unity ، تمامًا مثل MonoBehaviour العادي ، لكننا لم نعد بحاجة إلى إرفاق هذا البرنامج النصي إلى GameObject. بدلاً من ذلك ، ستتم معالجته مثل أي أصل عادي ، والذي يمكن إنشاؤه بنفس الطريقة التي يتم بها إنشاء تهيئة مسبقة أو مشهد أو مادة.

املأ النص البرمجي بحقول متسلسلة ، والتي ستحتوي على جميع البيانات المقابلة للمعلومات المعروضة في Sword Merchant UI.

 public class SwordData : ScriptableObject { [SerializeField] private string swordName; [SerializeField] private string description; [SerializeField] private Sprite icon; [SerializeField] private int goldCost; [SerializeField] private int attackDamage; } 

  • swordName : string ، حيث سيتم تخزين اسم السيف.
  • الوصف : string ، حيث سيتم تخزين وصف السيف.
  • الرمز : العفريت الذي سيحتوي على أيقونة السيف.
  • goldCost : int لتخزين قيمة السيف في الذهب.
  • attackDamage : int لتخزين الضرر عند الهجوم بالسيف.

ملاحظة: SerializeField

في Unity ، تتيح لك السمة SerializeField الحصول على متغيرات البرنامج النصي الخاصة المتاحة في المفتش. سيسمح لك بتعيين القيم في المحرر بدون توفير الوصول إلى المتغير من البرامج النصية الأخرى.

سيتطلب كل سيف تنفيذًا فريدًا خاصًا به لـ SwordData للكائن القابل للبرمجة . ولكن قبل أن نتمكن من إنشاء عمليات التنفيذ هذه ، نحتاج إلى إضافة كائن قابل للبرمجة إلى قائمة الأصول.

أضف كائن Scriptable إلى قائمة الأصول عن طريق إضافة السمة التالية إلى فئة SwordData :

 [CreateAssetMenu(fileName = "New SwordData", menuName = "Sword Data", order = 51)] public class SwordData : ScriptableObject 

  • fileName : الاسم الافتراضي عند إنشاء الأصل.
  • menuName : اسم الأصل المعروض في قائمة الأصول.
  • الترتيب : وضع الأصول في قائمة الأصول. تقسم الوحدة الأصول إلى مجموعات فرعية بعامل 50. وهذا يعني أن القيمة 51 تضع الأصل الجديد في المجموعة الثانية من قائمة الأصول.

إذا تم عمل كل شيء بشكل صحيح ، فيمكنك الانتقال إلى الأصول >> إنشاء وعرض أصل بيانات Sword Data الجديدة في القائمة. يجب أن يكون موجودًا في المجموعة الثانية ضمن أصول المجلد:


يمكنك أيضًا النقر بزر الماوس الأيمن في نافذة المشروع والاطلاع أيضًا على أصول بيانات Sword الجديدة:


إضافة البيانات


سننظم المشروع عن طريق إنشاء مجلد يسمى كائنات قابلة للبرمجة في مجلد البرامج النصية ، وداخل هذا المجلد مجلد آخر يسمى بيانات السيف .

داخل مجلد Sword Data الذي تم إنشاؤه حديثًا ، أنشئ أول أصول Sword Data.

يجب أن يظل الأصل الجديد لبيانات السيف يحمل الاسم الافتراضي المحدد مسبقًا fileName . حدد أحد الأصول وقم بتكرارها ست مرات ( Ctrl / Cmd + D ) لإنشاء سبعة أصول بيانات Sword ، واحد لكل من السيوف. الآن أعد تسمية كل أصل وفقًا للأبحاث الأولية:


انقر على أول أصول Sword Data في مجلد Sword Data وانظر إلى نافذة المفتش :


هنا نرى أصلًا يتم فيه تخزين معلومات حول سيف معين. املأ المعلومات لكل سيف. حاول أن تعطيهم وصفًا فريدًا وقيمة ذهبية وتلفًا أثناء الهجوم. في حقل Icon Sprite ، استخدم الرموز المتحركة المقابلة الموجودة في مجلد Sword Icons :


مبروك! لقد قمت بإنشاء كائن قابل للبرمجة وقمت بتكوين العديد من الأصول باستخدام هذا الكائن القابل للبرمجة.

استخدام كائن قابل للبرمجة


الآن سنبدأ في الحصول على البيانات من هذه الكائنات القابلة للبرمجة.

أولاً ، نحتاج إلى إضافة بعض طرق getter العامة حتى تتمكن البرامج النصية الأخرى من الوصول إلى الحقول الخاصة داخل الكائن القابل للبرمجة. افتح SwordData.cs وأضف ما يلي تحت الحقول المضافة سابقًا:

  public string SwordName { get { return swordName; } } public string Description { get { return description; } } public Sprite Icon { get { return icon; } } public int GoldCost { get { return goldCost; } } public int AttackDamage { get { return attackDamage; } } 

افتح Sword.cs وأضف الكود التالي:

  [SerializeField] private SwordData swordData; // 1 private void OnMouseDown() // 2 { Debug.Log(swordData.name); // 3 Debug.Log(swordData.Description); // 3 Debug.Log(swordData.Icon.name); // 3 Debug.Log(swordData.GoldCost); // 3 Debug.Log(swordData.AttackDamage); // 3 } 

إليك ما أضفناه بهذا الكود:

  1. حاوية البيانات لبيانات هذا السيف.
  2. OnMouseDown هي وظيفة MonoBehaviour مضمنة يتم استدعاؤها عندما يضغط المستخدم على زر الماوس الأيسر.
  3. أمثلة على كيفية الحصول على البيانات من أصول الكائن القابل للبرمجة

ارجع إلى الوحدة وانتقل إلى نافذة التسلسل الهرمي . حدد كائن لعبة 1_Longsword في السيف الجاهز. أضف أصل 1_Longsword Data المناسب إلى متغير Sword Data من البرنامج النصي Sword.cs في نافذة المفتش:


انقر فوق تشغيل ( Ctrl / Cmd + P ) في محرر الوحدة ، ثم انقر فوق أقصى سيف:


يجب أن تعرض وحدة التحكم معلومات تشبه البيانات المنقولة من أصول بيانات Sword.

كائنات قابلة للبرمجة تجعل من السهل استبدال هذه البيانات. حاول إدراج كائنات قابلة للبرمجة في بيانات السيف في حقل بيانات السيف.

كائنات قابلة للكتابة


لذا ، قمنا بإنشاء كائن قابل للبرمجة ، ورأيت كيف يمكنك الوصول إلى بياناته داخل اللعبة. لكننا ما زلنا بحاجة إلى دمج بيانات Sword مع واجهة المستخدم!

يمكنك استخدام نمط Singleton السريع والقذر لهذا الغرض. ومع ذلك ، لدينا الآن إمكانيات أخرى ...

... وهي كائنات قابلة للكتابة! سنستخدمها لإنشاء كود نظيف ومقسّم بدقة.

في هذا القسم ، ستتعلم كيفية إنشاء أحداث اللعبة باستخدام فئة UnityEvent .

لعبة أحداث ومستمعين


في مجلد البرامج النصية ، قم بإنشاء نصين : GameEvent.cs و GameEventListener.cs . يعتمدون على بعضهم البعض ، لذلك للتخلص من الأخطاء ، تحتاج إلى إنشاء كليهما.

 using System.Collections.Generic; using UnityEngine; [CreateAssetMenu(fileName = "New Game Event", menuName = "Game Event", order = 52)] // 1 public class GameEvent : ScriptableObject // 2 { private List<GameEventListener> listeners = new List<GameEventListener>(); // 3 public void Raise() // 4 { for (int i = listeners.Count - 1; i >= 0; i--) // 5 { listeners[i].OnEventRaised(); // 6 } } public void RegisterListener(GameEventListener listener) // 7 { listeners.Add(listener); } public void UnregisterListener(GameEventListener listener) // 8 { listeners.Remove(listener); } } 

إليك ما يفعله الرمز أعلاه:

  1. يضيف GameEvent كأصل إلى قائمة الأصول.
  2. GameEvent عبارة عن كائن قابل للبرمجة ، لذا يجب أن يرث من ScriptableObject.
  3. قائمة GameEventListeners للاشتراك في GameEvent.
  4. طريقة لاستدعاء جميع مشتركي GameEvent.
  5. سيكون GameEventListener الموقع الأخير هو أول استدعاء (آخر يأتي ، يخرج أولاً).
  6. استدعاء كل UnityEvent GameEventListeners.
  7. طريقة تسمح لـ GameEventListeners بالاشتراك في GameEvent.
  8. طريقة تسمح لـ GameEventListeners بإلغاء الاشتراك من GameEvent.


 using UnityEngine; using UnityEngine.Events; // 1 public class GameEventListener : MonoBehaviour { [SerializeField] private GameEvent gameEvent; // 2 [SerializeField] private UnityEvent response; // 3 private void OnEnable() // 4 { gameEvent.RegisterListener(this); } private void OnDisable() // 5 { gameEvent.UnregisterListener(this); } public void OnEventRaised() // 6 { response.Invoke(); } } 

في الكود الموضح أعلاه ، يواصل المشروع تطوير:

  1. متطلبات استخدام فئة UnityEvent.
  2. GameEvent التي ستشترك فيها GameEventListener.
  3. استجابة UnityEvent التي سيتم رفعها عند طرح حدث GameEvent هذا GameEventListener.
  4. ربط GameEvent بـ GameEventListener عند تمكين GameObject.
  5. ربط GameEvent من GameEventListener عند تعطيل GameObject.
  6. يتم استدعاؤه عند إنشاء GameEvent الذي يتسبب في قيام GameEventListener باستدعاء حدث UnityEvent.

هل هو صعب؟ لا شيء ، ستكتشف ذلك بمرور الوقت!

تدريب المحرر


عد إلى محرر الوحدة وقم بإنشاء مجلد أحداث جديد في البرامج النصية >> ScriptableObjects. ثم قم بإنشاء سبعة أحداث لعبة من قائمة الأصول ، كما فعلنا مع كل أصل من بيانات Sword Data. ضعهم في مجلد أحداث اللعبة الجديد.


استبدل الرمز الموجود داخل البرنامج النصي Sword.cs بالسطور التالية:

  [SerializeField] private GameEvent OnSwordSelected; // 1 private void OnMouseDown() { OnSwordSelected.Raise(); // 2 } 

يضيف هذا الرمز احتمالين إلى متجر تاجر السيف:

  1. جيل حدث اللعبة عند اختيار السيف.
  2. توليد الأحداث عند النقر على السيف.

احفظ النص. الآن ، في كل GameObject من التسلسل الهرمي للسيف ، قم بتوصيل حدث OnSwordSelected المقابل.


كل سيف لديه الآن رابط للحدث الذي يتم تشغيله عند النقر على السيف.

تكامل واجهة المستخدم


الآن أنت بحاجة لجعل واجهة المستخدم تعمل. هدفنا هو عرض بيانات السيف المقابلة عند النقر على كل سيف.

روابط واجهة المستخدم


قبل تحديث واجهة المستخدم ، يجب الحصول على رابط لكل عنصر من عناصر واجهة المستخدم. لنبدأ بإنشاء نص جديد يسمى SwordMerchant.cs وإضافة الكود التالي إلى هذا النص الجديد:

 using UnityEngine; using UnityEngine.UI; public class SwordMerchant : MonoBehaviour { [SerializeField] private Text swordName; // 1 [SerializeField] private Text description; // 2 [SerializeField] private Image icon; // 3 [SerializeField] private Text goldCost; // 4 [SerializeField] private Text attackDamage; // 5 } 

باستخدام هذا الرمز ، أضفنا ما يلي:

  1. مرجع إلى مكون النص لكائن اللعبة NameText .
  2. ارتباط بمكون النص لكائن اللعبة DescriptionText .
  3. رابط لمكون صورة كائن لعبة Sword_Icon .
  4. ارتباط بمكون النص لكائن اللعبة GoldText .
  5. ارتباط إلى مكون النص لكائن لعبة AttackText .

توجد كائنات اللعبة المذكورة أعلاه في SwordMerchantCanvas >> SwordMerchantPanel لنافذة التسلسل الهرمي. قم بإضافة البرنامج النصي إلى GameObject SwordMerchantCanvas ، ثم قم بتكوين كافة الارتباطات:


المستمعين وردود واجهة المستخدم


تحتوي جميع السيوف على حدث يمكن لواجهة المستخدم الاشتراك فيه باستخدام البرنامج النصي GameEventListener . أضف GameEventListener لكل حدث OnSwordSelected إلى GameObject SwordMerchantCanvas :


كما ترون ، فإن مستمع أحداث الألعاب لدينا يحتوي على مجالين: حدث أحداث اللعبة الذي يستمع إليه ، والاستجابة التي تظهر عند إنشاء حدث اللعبة.

في حالتنا ، سيتم تحديث الاستجابة بواسطة واجهة المستخدم. أضف الطريقة التالية إلى البرنامج النصي SwordMerchant.cs :

  public void UpdateDisplayUI(SwordData swordData) { swordName.text = swordData.SwordName; description.text = swordData.Description; icon.sprite = swordData.Icon; goldCost.text = swordData.GoldCost.ToString(); attackDamage.text = swordData.AttackDamage.ToString(); } 

تستقبل هذه الطريقة أصل بيانات Sword Data ، ثم تقوم بتحديث كل حقل لواجهة المستخدم بقيمة حقل Sword Data المطابق. لاحظ أن GoldCost و AttackDamage ترجع عددًا صحيحًا ، لذلك تحتاج إلى تحويلها إلى سلسلة للنص.

باستخدام طريقتنا الجديدة ، يمكننا إضافة رد على كل GameEventListener .

لكل رد تضيفه ، تحتاج إلى رابط إلى كائن لعبة SwordMerchantCanvas كقيمة حقل بلا (كائن) . بعد ذلك ، حدد SwordMerchant.UpdateDisplayUI من القائمة المنسدلة على يمين القائمة المنسدلة Runtime Only .

كن حذرًا واستخدم أصول بيانات Sword الصحيحة لكل حدث OnSwordSelected .


الآن يمكننا أن نبدأ اللعبة ، انقر على السيف ونرى أنه يتم تحديث واجهة المستخدم وفقًا لذلك!


نظرًا لأننا نستخدم أحداث اللعبة ، يمكنك ببساطة SwordMerchantCanvas ، وسيظل كل شيء يعمل ، فقط بدون واجهة مستخدم. هذا يعني أن المباني الجاهزة للسيف منفصلة عن SwordMerchantCanvas .

إلى أين أذهب بعد ذلك؟


إذا فاتك شيء أثناء القصة ، يمكنك تنزيل المشروع النهائي ، الموجود في مواد البرنامج التعليمي.

إذا كنت تريد المضي قدمًا ، فحاول أن تجعل كل سيف يعيد إنتاج صوته الخاص. حاول توسيع بيانات سيف الكائن OnSwordSelected والاستماع إلى أحداث OnSwordSelected .

هل تريد معرفة المزيد عن الوحدة؟ تحقق من سلسلة فيديو Unity أو اقرأ دروس Unity .

Source: https://habr.com/ru/post/ar421523/


All Articles