مقدمة
مرحبًا أيها القراء الأعزاء ، أود في مقال اليوم أن أتطرق إلى مثل هذه الظاهرة في تطوير التطبيقات على
Unity3d كتطور مرئي أو ، بشكل أدق ، تطوير باستخدام التمثيل المرئي للرمز والمنطق. وقبل المتابعة ، أريد أن أوضح على الفور ، الأمر لا يتعلق بالبرمجة المرئية ، من كلمة "مطلقة" ، لا توجد
صيغ مخطط في عالم الوحدة ولا توجد أجيال من رموز C #. إذن ما الذي يعنيه محرر المنطق البصري؟ إذا كنت مهتمًا بالإجابة على هذا السؤال ، فمرحبًا بك في برنامج cat.
مقالات في السلسلة:
محرر المنطق البصري الجزء 2ما هو محرر المنطق البصري
في كثير من الأحيان ، ويرى البعض أنه دائمًا ، أثناء التطوير ، يقوم المبرمجون بكتابة الكثير من التعليمات البرمجية المختلفة التي تقوم بالكثير من الأشياء المختلفة ، من أدوات النظام إلى ميكانيكي اللعبة. هذا الرمز ، إذا كان المبرمج "حقيقي" ، عادة ما يكون موحدًا ومعزولًا بحيث يمكن إعادة استخدامه (ضمن Unity ، هذا الرمز هو مكونات ، كما أنهم
يرثون MonoBehavior ). ليس من الصعب تخيل أنه يمكن أن يكون هناك الكثير من هذه الشفرة ، خاصة إذا لم يكن هذا هو المشروع الأول. الآن تخيل أننا نبدأ مشروعًا جديدًا ونحتاج إلى تقديم الكثير من النماذج الأولية السريعة والمختلفة ، وفريق المبرمجين محدود ، والكل مشغول بالمشروع أو المشاريع الرئيسية. مصممو اللعبة غاضبون ، فهم بحاجة إلى الاختبار والتحقق من أن المنتجين يركضون حول المديرين الذين يحاولون الحصول على مبرمج لأنفسهم ، والمال محدود ، والوقت ينفد ، إلخ.
على الجانب الآخر للعملة ، كتبنا (المبرمجين) الكثير من التعليمات البرمجية في شكل مكونات ، علقوا في قائمة كبيرة على أشياء مختلفة في المشهد. وهكذا ، قمنا بتوسيع الفريق ، وتوظيف مبرمج جديد ، وهو يفتح المجال لفرزها ويغرق في فوضى من الأسئلة: من الذي يتسبب في من ، وبأي ترتيب ، أي مكون مرتبط بأي وكيف وكيف ، وما إلى ذلك. أنت تقول بشكل معقول: - "و الوثائق؟ " هناك وثائق (على الرغم من أن ذلك ليس حقيقة على الإطلاق) ، ولكن هنا يتعلق الحد الأدنى للأفراد الجدد الذين ينضمون إلى الفريق بأدنى مستوى ممكن ، ووقت هذه العملية أقصر ما يمكن.
كيفية حل الحالات المذكورة أعلاه؟ الجواب في عنوان المقال هو محرر المنطق البصري. ما هذا؟ هذه بيئة تسمح لك بالعمل بصريًا على مختلف مكونات المنطق وتكوين علاقاتها (في الإصدار "اللين") ، وكذلك التعامل مع كائنات المشهد بشكل غير مباشر من المشهد. إذا كنت تصفها في شكل بسيط ورائع ، فسيكون في مرحلة الطفولة تجميع تصميمات مختلفة عن المكعبات (فقط في حالتنا ، لا تكون المكعبات متصلة بإحكام ، وتزيل القاع ، ولن يسقط تصميمنا).
لذلك ، اكتشفنا التعريف ، لكن ما الذي يعطينا هذا في النهاية؟
- يمكنك تجميع التصميمات العالمية التي يمكن إعادة استخدامها في المشاريع ، مما يقلل من الروتين اللاحق. تخيل نوعًا من الحقول النقية ، وهو مشروعنا ، فنحن نأخذ فقط الإنشاءات المجمعة من لعبة أخرى ، ونضعها في الميدان وهذا كل شيء.
- يمكنك إنشاء قاعدة بيانات لـ "المكعبات" المعزولة (الميكانيكا ، والمنطق ، والوظيفية) التي يمكن للأشخاص الذين ليسوا مبرمجين بناء بنى خاصة بهم.
- من الممكن استبدال التصميمات أثناء التنقل بأخرى ، مما يؤدي إلى تغيير سلوك المنطق.
- يمكنك استخدام الإنشاءات في الوضع المؤجل ، على سبيل المثال ، إذا لم يكن NPC موجودًا في العالم الآن ، فلن يكون هناك منطق مرتبط به في "مجالنا".
- نظرًا لأن مكعباتنا غير مرتبطة بعلاقات متشددة ، يمكننا إيقاف تشغيلها كما نرغب وننفذ تفرع شرطي وغير مشروط معقد.
حسنًا ، هل هذا الصوت جيد جدًا؟ لكن ماذا في الواقع؟ إذا قمت بفتح
Asset Store وشاهدت قسم
Scripting المرئي ، يمكنك أن ترى ، من حيث المبدأ ، عددًا كبيرًا من المكونات الإضافية المختلفة. معظمها عبارة عن صيغ مختلفة عن سمة Blueprint من Unreal Engine ، أي في جوهرها ، توليد الكود. لا يوجد عمليا أي أنظمة تناسب مفاهيم محرر المنطق البصري. الأقرب في المعنى هي:
- صانع الألعاب. نعم إنه مكون إضافي لـ FSM ، ومع ذلك ، فهو يتيح لك كتابة الإجراءات الخاصة بك. ليست مريحة للغاية من وجهة نظر الواجهة ، لكنها جيدة جدًا بالنسبة لبعض الأشياء. عاصفة ثلجية لم يكن عبثا المستخدمة في حجر الموقد.
- مصمم السلوك / سلوك القمر ، إلخ. الإضافات شجرة الدولة. إنه أقرب إلى ما تم وصفه أعلاه ، ولكن هناك الكثير من القيود ، بعد كل شيء ، فإن شجرة الحالة ليست منطقًا مكتملًا للمكونات.
- ICode. هذا هو التناظرية لصانع الألعاب ، وهذا هو ، في الواقع ، أيضا آلة الدولة.
هل هناك طريقة للخروج تسأل ، أيها القراء الأعزاء؟ لقد وجدت واحدة فقط ، اكتب نظامي ، الذي قمت به ، لكن الطريق إلى ذلك كان طويلًا وشائكًا.
الطريق
نشأت فكرة تطوير مكون إضافي لمحرر المنطق المرئي لـ
Unity3D منذ فترة طويلة. في البداية كانت الأفكار فقط ، إذا كان الأمر كذلك ، فسيكون ذلك رائعًا. ظهرت هذه الأفكار في عملية العمل على مشروع كان فيه الكثير من الألعاب المماثلة ، أكثر من 20 قطعة يجب القيام بها بسرعة كبيرة. كان التطبيق الأول فظيعًا من حيث الواجهة ، رغم أنه ، بالطبع ، سمح لنا بتطوير مجموعة الألعاب بالكامل بنجاح بسرعة معينة.
بالنسبة للمشروع التالي ، تقرر إنشاء محرر مرئي كامل ، ولكن نتيجة للتجربة القليلة ، لم يكن التنفيذ ناجحًا ، كان كل شيء بطيئًا إلى حد كبير ، وتراجع عدد الاتصالات ، وما إلى ذلك ، لدرجة أنه كان من المستحيل معرفة ماذا وأين (انظر لقطة ولا تخافوا).

بعد ذلك ، تم تأجيل الفكرة لبعض الوقت. المشاريع التالية التي قمت بها بالفعل على الكود الخالص ، لكن الفكرة ما زالت في ذهني. تدريجيا ، مع الأخذ في الاعتبار أخطاء الماضي ، تم تشكيل الرؤية النهائية (كما يبدو لي) وقائمة المتطلبات. وفي عام 2017 ، بعد الانتهاء من المشروع المستقل التالي ، قررت أن أتمكن من قضاء 6-7 أشهر في العمل على هذا البرنامج المساعد ومحاولة وضعه في
متجر الأصول (لا يزال هذا الكذب يسمى
Panthea VS ). من وجهة نظر الخبرة في العمل في مثل هذا المشروع المعقد ، كان كل شيء رائعًا للغاية ، والجانب المالي محزن ، ولا يزال قادرًا على البرمجة والقدرة على البيع شيئان مختلفان. في نوفمبر 2017 ، بعد ذلك فقدت دوافعي قليلاً ، طلقت ، غيرت مدينتي ، غيرت حياتي تمامًا ، ولكي لا أقع في samoyedism قررت أن أنظر إلى زاوية مختلفة حول موضوع محرر المنطق البصري. كانت النتيجة
uViLEd ، والتي قررت النشر مجانًا. منذ أن وقعت عقدًا بدوام كامل ، اضطررت للعمل عليه في عطلات نهاية الأسبوع والأعياد ، واستغرق الأمر مني عام 2018 وبداية 2019. يعد
uViLEd بمثابة إعادة تفكير كبيرة في
Panthea VS ، وهو إعادة تشكيل كاملة لرمز برنامج التحويل البرمجي Roslyn (C # 7+) ، لذلك كل شيء يعمل فقط من إصدار Unity3d 2018.3.
ملاحظة : أطلقت
Panthea VS العديد من المشروعات (Android و iOS ، لا سيما Lev Lev Truck والسيارات) ، من حيث المبدأ ، كانت تجربة استخدامه ناجحة ، ولكن ظهرت اللحظة التي تكتب فيها محررًا ، وهناك شيء آخر هو تعلم كيفية استخدامها بشكل صحيح (بغض النظر عن مدى غرابة ذلك) ).
uViLEd وكيفية استخدامها
مقدمة
لذا ، ما حدث في النهاية ، أولاً ننظر إلى الصورة ، ثم المتابعة (سيكون هناك المزيد من الصور).

ما هو محرر المنطق البصري القائم على؟

هنا:
- المكونات - هذا هو رمزنا الذي يقوم بتنفيذ واحد أو آخر وظيفي ، في الواقع ، تمثيلي لـ MonoBehaviour ، فقط في حالتنا يتم توريث جميع المكونات من فئة LogicComponent ، والتي بدورها عبارة عن ScriptableObject .
- المتغيرات هي ScriptableObjects الخاصة المسموح بها لتخزين البيانات (أي ، بما في ذلك الهياكل والفئات المخصصة ، والمراجع إلى كائنات المشهد ، والأبنية الجاهزة والأصول). هناك حاجة إلى المتغيرات إذا كان ذلك ضروريًا لجعل البيانات مشتركة بين المكونات ، أي أنه يمكن لكل مكون الرجوع إلى متغير من النوع المطلوب ، وسيكون واحدًا.
- العلاقات هي وصف في شكل مرئي للمكونات ، وكيف وبأي ترتيب استدعاء أساليب بعضها البعض. يتم تحديد العلاقات بين المكونات باستخدام مجالين متخصصين من الأنواع INPUT_POINT و OUTPUT_POINT . يتم تكوين ارتباط دائمًا كنقطة إخراج مكون إلى نقطة إدخال مكون آخر. هذه الاتصالات ليست جامدة ، أي أنها غير مرئية للمبرمج وليست في الكود أيضًا. كانت موجودة ، فقط في المحرر ، ثم عندما يبدأ المشهد ، فإن وحدة التحكم المنطقي نفسها تتفهم الكود. كيف يحدث هذا سنتحدث في مقالة منفصلة.
كل شيء في المقصورة - المكونات والمتغيرات والعلاقات - يشكل
المنطق . بشكل عام ، لا شيء معقد للغاية ، يكتب المبرمج رمز المكونات والمتغيرات ، ومصمم / لعبة مبرمج / نص برمجي آخر (أو نفس واحد) يشكل المنطق عن طريق وضع هذه المكونات في المحرر وإعداد الاتصالات والمعلمات.
الملامح الرئيسية uViLEd
- تشغيل المنطق (مجموعة من المكونات والمتغيرات والعلاقات) في الوضع المؤجل ، بما في ذلك البدء من مصدر خارجي (القرص الثابت أو الخادم)
- إعداد الاتصالات بين المكونات (ترتيب المكالمات ، التنشيط وإلغاء تنشيط)
- سهولة دمج المكونات وأي كود آخر ، بما في ذلك أحفاد MonoBehavior
- تجاوز مظهر المكونات في المحرر (مماثل لـ CustomPropertyDrawer)
- تكوين إعدادات المكون من خلال مفتش Unity3d
- أضف المكونات بسهولة إلى المنطق من خلال ملف البرنامج النصي السحب والإفلات أو من خلال الدليل
- تجميع المكونات في محرر المنطق
- ضبط عرض المكونات في المحرر (الانعكاس والتصغير والتنشيط وإلغاء التنشيط)
- فتح محرر رمز المكون مباشرة من محرر المنطق
- عرض تصحيح الأخطاء البيانات مباشرة في محرر المنطق أثناء بدء التشغيل في المحرر
- تحجيم محرر المنطق البصري
- إذا تم تضمين عدد كبير من المكونات في المنطق فجأة ، فهناك إمكانية البحث عنها مع التركيز عند التحديد (وهذا ينطبق على المتغيرات)
- تصحيح الأخطاء خطوة بخطوة في وضع تشغيل المشهد في محرر Unity3d مع تتبع جميع البيانات المرسلة بين المكونات والقيم المتغيرة
- دعم أساليب MonoBehaviour وتحديد ترتيب مكالمتهم. ملاحظة : هنا نعني بشكل افتراضي في SO عدم وجود طرق مثل Start ، Update ، إلخ. لذلك ، تمت إضافة دعمهم إلى المكونات نفسها. في نفس الوقت ، باستخدام سمة ExecuteOrder ، يمكنك تكوين الترتيب الذي يتم من خلاله استدعاء أساليب البدء والتحديث وما إلى ذلك.
- دعم Coroutine و async / await وجميع سمات Unity3d للمفتش ، وكذلك دعم CustomPropertyDrawer
العمل مع المحرر
لبدء العمل مع المحرر ، يجب عليك فتح المشهد ، ثم بدء تشغيل المحرر نفسه.

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

بعد إضافة العديد من المكونات إلى المنطق ، يمكن نقلها ، بما في ذلك في مجموعات أو دمجها في مجموعة مرئية.

دعونا نفكر بمزيد من التفصيل في ما نمثله المكون نفسه في محرر مرئي.

هنا:
- زر قائمة المكون ، يفتح قائمة منسدلة يمكنك من خلالها:
- تنشيط أو إلغاء تنشيط مكون
- تصغير المكون (يمكن القيام بذلك أيضًا عن طريق النقر المزدوج على الرأس)
- عكس المكوّن (نقاط تبادل المدخلات والمخرجات)
- إخفاء أو إظهار منطقة خيارات المكون
- افتح محرر الكود للمكون
- مساحة معلمات المكون هي المكان الذي يتم فيه عرض قيم المعلمات الرئيسية للمكون ، والتي يعتمد تكوينها على المبرمج
لتكوين المعلمات (الحقول أو الحقول العامة باستخدام سمة SerializeField) ، تحتاج إلى تحديد المكون في محرر المنطق وفتح Unity3d inspector.

هنا:
- في الزاوية اليمنى العليا هو زر يتيح لك تغيير لون الرأس ، والذي يتم عرضه في محرر المنطق
- الاسم - حقل لتعيين اسم مثيل المكون
- تعليق - حقل لإعداد تعليق على مثيل المكون ؛ يتم عرضه في محرر المنطق عندما تحوم فوق المكون
- معلمات المكون - المنطقة التي يتم فيها عرض معلمات المكون (الحقول والحقول العامة التي تحمل علامة SerializeField)
- الروابط المتغيرة - منطقة لإعداد الإشارات إلى المتغيرات (ستتم مناقشة المزيد عنها في القسم الخاص بالعمل مع المتغيرات).
من أجل تجميع الكائنات بصريًا ، تحتاج إلى تحديدها ، ثم اضغط على الزر الأيمن وحدد العنصر المقابل في القائمة. يمكن إعادة تسمية المجموعات ، وكذلك تغيير نظام الألوان.

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



يتم تأسيس العلاقات بناءً على قاعدة مطابقة الكتابة التي تنقلها نقطة ما وتستقبلها. يتم إجراء استثناءات لنقطة إدخال لا تستقبل البيانات ؛ يمكن توصيل أي نقطة إخراج بها. عند إنشاء اتصال ، يقوم النظام تلقائيًا بالتحقق من مطابقة الكتابة ويظهر ما إذا كان يمكن إنشاء هذا الاتصال أم لا. يتم تعيين نقاط الإدخال والإخراج في رمز المكون باستخدام الفئات التالية:
INPUT_POINT OUTPUT_POINT INPUT_POINT<T> OUTPUT_POINT<T>
يتم استخدام الفئتين الأوليين لنقاط الإدخال والإخراج التي لا تقبل المعلمات ، والثانية ، على التوالي ، والعكس بالعكس. تي يمكن أن يكون أي نوع.
public INPUT_POINT <float> InputFloatValue = new INPUT_POINT<float>(); public OUTPUT_POINT <float> OutputFloatValue = new OUTPUT_POINT<float>();
للاتصال بسلسلة من الروابط ، يجب عليك استخدام وظيفة التنفيذ.
OutputFloatValue.Execute(5f);
من أجل معالجة مثل هذه المكالمة ، من الضروري تعيين معالج لنقطة الإدخال في رمز المكون (حول المكان الذي سنتحدث فيه بالضبط بعد ذلك بقليل).
InputFloatValue.Handler = value => Debug.Log(value);
وأخيرا ، أود أن أذكر نقطة مهمة حول الاتصالات. إذا كان هناك العديد من الروابط من نقطة واحدة ، فمن الممكن في المحرر ضبط ترتيب مكالمتهم.
العمل مع المتغيرات
كما ذكرنا سابقًا ، المتغيرات هي كائنات خاصة تتيح لك مشاركة البيانات بين المكونات من خلال روابط لها. يتم إنشاء المتغيرات ، مثل المكونات ، بواسطة المبرمجين.
[ComponentDefinition(Name = "Float", Path = "uViLEd Components/Base/Variable/Base", Tooltip = "Variable for a floating-point number", Color = VLEColor.Cyan)] public class VariableFloat : Variable<float> { }
كما ترون ، الفئة الأساسية للمتغيرات هي الفئة العامة المتغير ، حيث T هي نوع البيانات المحاطة بالمتغير ، يمكن أن يكون T أي نوع يمكن تسلسله.
في المحرر ، يتم عرض المتغيرات على النحو التالي:

لتغيير عرض القيم المتغيرة ، ما عليك سوى إعادة تحديد طريقة ToString من النوع T.
public struct CustomData { public readonly int Value01; public readonly int Value02; public CustomData (int value01, int value02) { Value01= value01; Value02= value02; } public override string ToString() { var stringBuilder = new StringBuilder(); stringBuilder.AppendLine("Value01 = {0}".Fmt(Value01)); stringBuilder.Append("Value02 = {0}".Fmt(Value02)); return stringBuilder.ToString(); } }
وبالتالي ، سيبدو متغير من هذا النوع:
public class VariableCustomData : Variable<CustomData> { }
لإضافة مرجع إلى متغير في مكون ، يجب عليك استخدام فئة خاصة.
public VARIABLE_LINK<CustomData> CustomVariableLink = new VARIABLE_LINK<CustomData>();
بعد ذلك ، يمكن تعيين الارتباط في المفتش ، وفي القائمة المنسدلة ، لن يتم عرض سوى متغيرات من نوع
CustomData ، مما يسهل إلى حد كبير العمل معهم.
لتوفير الراحة للعمل مع المتغيرات ، هناك طرق خاصة تسمح لك بتحديد متى قام المتغير بتغيير قيمته أو عند تعيين أي بيانات عليه.
CustomVariableLink.AddSetEventHandler(CustomDataSet); CustomVariableLink.AddChangedEventHandler(CustomDataChanged);
يجب أن يؤخذ في الاعتبار أن Changed يعمل وفقًا لحالة
Equals ، لذلك إذا تم استخدام الهياكل والفئات ، فيجب إعادة تعريف هذه الطريقة لضمان التشغيل الصحيح.
العمل مع كائنات الوحدة
نظرًا لطبيعة نظام uViLEd ، لا يمكن استخدام الروابط المباشرة لكائنات Unity فيه ، حيث لا يمكن استعادتها عند تحميل المنطق. لحل هذه المشكلة ، تم إنشاء غلاف
VLObject متخصص ، والذي يسمح لك بإنشاء مثل هذه الروابط ، وكذلك حفظها وتحميلها. من بين أشياء أخرى ، تحتوي هذه shell على محرر خاصية خاص يتيح لك الحصول على مكونات من أي كائن في المشهد (انظر الشكل أدناه) إذا كنت تريد الوصول إليها. باستخدام
VLObject ، يمكنك تخزين الارتباطات ليس فقط لكائنات المشهد ومكوناتها ، ولكن أيضًا للأبنية الجاهزة وملفات الموارد ، مثل القوام ، الأصوات ، إلخ.
ملاحظة : إذا تم استخدام المنطق الحالي في مشهد آخر ، فستفقد الإشارات إلى الكائنات ، بما في ذلك الإشارات إلى المباني الجاهزة ، لأن المشهد يعمل كخزن لهم. يجب أيضًا أخذ ذلك في الاعتبار إذا كنت تخطط لاستخدام المنطق كقالب ، في هذه الحالة ، فإن أفضل خيار هو نقل الروابط الضرورية إليه من الخارج (على سبيل المثال ، من المنطق المتصل بالمشهد).
من الممكن أيضًا تقييد نوع كائن الوحدة الذي سيتم تثبيته في
VLObject . يؤثر هذا على مفتش الوحدة فقط ويستخدم لتسهيل العمل معهم.
[SerializeField] [TypeConstraint(typeof(Button))] private VLObject _button;
إنشاء مكون المنطق
لإنشاء مكون منطقي ، يحتاج المبرمج فقط إلى إضافة ملف نصي C # بسيط إلى المشروع (يمكنك أيضًا إنشاء مكون أو متغير فورًا من خلال قائمة خاصة في علامة التبويب Project) وتغيير الكود الموجود فيه إلى ما يلي:
[ComponentDefinition(Name = "MyComponent", Path = "MyFolder/MySubfolder", Tooltip = "this my logic component", Color = VSEColor.Green)] public class MyLogicComponent : LogicComponent { }
كما ذكرنا سابقًا ،
ComponentDefinition هي سمة تسمح لك بإنشاء كتالوج للمكونات تلقائيًا ، تجدر الإشارة هنا إلى أن Color (لون الرأس) مضبوط في السلسلة كتنسيق HEX.
LogicComponent هي الفئة الأساسية لجميع المكونات ، والتي بدورها هي سليل
ScripatableObject .
فيما يلي مثال بسيط للمكون الذي يتفوق على قيمة واردة من نوع bool:
public class IfBool : LogicComponent { public INPUT_POINT<bool> ValueToBeChecked = new INPUT_POINT<bool>(); public OUTPUT_POINT True = new OUTPUT_POINT(); public OUTPUT_POINT False = new OUTPUT_POINT(); public override void Constructor() { ValueToBeChecked.Handler = ValueToBeCheckedHandler; } private void ValueToBeCheckedHandler(bool value) { if(value) { True.Execute(); }else { False.Execute(); } } }
لذلك ، كما ترون من الشفرة ، أنشأنا نقطة إدخال المكون ، والتي تأخذ قيمة type bool ونقطتي مخرجات تسمى وفقًا للقيمة التي حصلنا عليها.
ربما لديك الآن سؤال ، ما نوع
المنشئ ؟ أشرح. بشكل افتراضي ، لا يدعم
ScriptableObject أساليب مثل
البدء والتحديث وما إلى ذلك ، لكنه يدعم أيضًا الأساليب
Awake و
OnEnable و
OnDisable و
OnDestroy . إذاً ،
فهناك Awake (مثل
OnEnable ) ، في حالة إنشاء
ScriptableObject من خلال الأسلوب
CreateInstance الذي يطلق عليه دائمًا ، وفي الحقيقة ، هذه هي المشكلة. نظرًا لحقيقة أن الكائن تم إنشاؤه في الذاكرة للتسلسل في وضع المحرر ، كان من الضروري استبعاد رمز المكون من العمل في هذه اللحظة ، لذلك تمت إضافة التناظرية
Awake كأسلوب
Constructor ، وينطبق الشيء نفسه على أساليب
OnDisable و
OnDestroy عند حذف كائن في المحرر. إذا كنت بحاجة إلى معالجة إزالة مكون بشكل صحيح (عند إلغاء تحميل مشهد ، على سبيل المثال) ، فيجب عليك استخدام واجهة
IDisposable .
بشكل عام ، كما ترون ، لا يوجد شيء صعب في إنشاء المكونات. هذا فصل عادي ، حيث يمكن أن يكون هناك أي كود تريده. في الحالة المعينة ، قد لا تحتوي المكونات على نقاط إدخال وإخراج على الإطلاق ، ولكنها تتصل باستخدام الرسائل العالمية. بالمناسبة ، لهذا يوجد في
uViLEd فئة
GlobalEvent - إنه نظام رسائل يعتمد على أنواع البيانات (يمكن العثور على المزيد حوله في مقالتي).
آخر شيء أود ذكره هو القدرة على تكوين نقاط المدخلات والمخرجات للمكون بناءً على معلمات المكون.

للقيام بذلك ، في رمز المكون ، يكفي تطبيق واحد أو كلا من
واجهات IInputPointParse و
IOutputPointParse . فيما يلي مثال على رمز الفئة العامة المجردة لمكونات فرع
التبديل ؛ يتم إنشاء نقاط الإخراج تلقائيًا هنا ، اعتمادًا على المعلمة
SwitchValues .
رمز الفصل SwitchAbstract public abstract class SwitchAbstract<T> : LogicComponent, IOutputPointParse { [Tooltip("input point for transmitting value, which should be checked")] public INPUT_POINT<T> ValueToBeChecked = new INPUT_POINT<T>(); [Tooltip("set of values for branching")] public List<T> SwitchValues = new List<T>(); protected Dictionary<string, object> outputPoints = new Dictionary<string, object>(); public override void Constructor() { ValueToBeChecked.Handler = ValueToBeCheckedHandler; } protected virtual bool CompareEqual(T first, T second) { return first.Equals(second); } protected virtual string GetValueString(T value) { var outputPontName = value.ToString(); #if UNITY_EDITOR if (!UnityEditor.EditorApplication.isPlaying) { if (outputPoints.ContainsKey(outputPontName)) { outputPontName += " ({0})".Fmt(outputPoints.Count); } } #endif return outputPontName; } private void ValueToBeCheckedHandler(T checkedValue) { foreach (var value in SwitchValues) { if (CompareEqual(checkedValue, value)) { ((OUTPUT_POINT)outputPoints[GetValueString(value)]).Execute(); return; } } } public IDictionary<string, object> GetOutputPoints() { #if UNITY_EDITOR if (!UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode) { outputPoints.Clear(); } #endif if (outputPoints.Count == 0) { foreach (var value in SwitchValues) { outputPoints.Add(GetValueString(value), new OUTPUT_POINT()); } } return outputPoints; } }
تصحيح المنطق
يوفر UViLEd عدة آليات لتصحيح منطق:
- القدرة على عرض المتغيرات الداخلية وقيمها في محرر المنطق في وضع تشغيل المشهد. للقيام بذلك ، استخدم سمة ViewInDebugMode
- القدرة على عرض قيم متغيرات المنطق في وضع تشغيل المشهد
- إمكانية تصحيح الأخطاء خطوة بخطوة للمكالمات بين المكونات وعرض البيانات التي يتم نقلها بينهما
يحتوي UViLEd على وضع خاص للعنصر الأخير ، والذي يتم تشغيله عند بدء تشغيل المشهد.

يحتوي هذا الوضع ، للأسف ، على بعض القيود المرتبطة بالانتقال بين المشاهد. في هذه الحالة ، ستفقد بيانات تصحيح الأخطاء من المشهد السابق والمنطق ، وسيبدأ عرضها في الحالة الجديدة فقط منذ اللحظة التي يتم فيها تنشيط المنطق في المحرر.
استنتاج
في هذه المقالة حاولت أن أقدم لكم بإيجاز لنهج التطوير الذي أستخدمه في مشاريعي الحالية. على الرغم من الشكوك الأولية (بما في ذلك لي) ، تُظهر الممارسة بشكل كبير راحة استخدامه ، خاصة عند استخدام النماذج الأولية. من بين أشياء أخرى ، تم تبسيط عمل مصممي اللعبة إلى حد كبير ، فهم لا يذهبون إلى المشهد ، ولا يكزون الأشياء لتكوين عملية اللعبة ، ويتم إنشاء منطق منفصل لهم بمجموعة من البيانات من المتغيرات والمكونات التي يمكنهم من خلالها تكوين كل شيء بسهولة. من المزايا الكبيرة أيضًا حقيقة أنه في مشاريعي ، غالبًا ما يتم تنزيل المحتوى من الخارج. باستخدام محرر المنطق المرئي ، يمكنني تحديث رصيد عملية اللعبة دون تحديث التطبيق الرئيسي ، وفي بعض الحالات ، يمكن تغيير المنطق نفسه.
بالنسبة لي ، قررت أن مثل هذا النهج في التنمية هو المكان المناسب تمامًا ، وبالطبع لا ينطبق على المشاريع الكبيرة ، ولكن يمكن استخدامه هناك لبعض نصوص اللعب لإحياء العالم ، وفي تصميم المستوى ، إلخ. المشاريع الجارية (شريحة الأطفال) ، حتى الآن ، وقال انه يظهر نتائج رائعة.
ماذا بعد؟
كان هذا الجزء الأول من سلسلة من المقالات حول المحرر المرئي للمنطق uViLEd ، ثم ستكون هناك أجزاء حول:
- جوهر النظام : كيف يتم تحميل المنطق ، ولماذا يتم تحديد ScriptableObject ، وكيف يتم ترتيب API ، والذي يسمح لك بالقيام ، وما إلى ذلك ، ما هي الصعوبات التي نشأت وكيف تم حل كل شيء.
- المحرر : كيف تم تطويره ، وكيف تم بناؤه ، وما هي المشاكل وما هي الحلول ، وما إلى ذلك الأشياء ، التي سأعيد تشكيلها الآن.
اكتب التعليقات إذا كان لديك أي أسئلة محددة تودّ تغطيتها في المقالات التالية.
ملاحظة : حاولت التحدث عن النقاط الرئيسية في
uViLEd ، إذا كنت ترغب في ذلك ، فيمكنك التعرف عليه من خلال تنزيل المكون الإضافي من Asset Store ، وهناك وثائق كاملة (على الرغم من اللغة الإنجليزية): دليل المستخدم ، ودليل للمبرمجين وواجهات برمجة التطبيقات.
محرر المنطق البصري الجزء 2محرر المنطق البصري UViLEdالمراسلة العالمية المادة