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

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

تحقق من القراءات ، وقم بتشغيل مفتاح التبديل الموجود على اليسار ، وقم بتشغيل الذراع على اليمين ، وشد الصمام الأحمر. لا تخلط ولا تنسى.
في البداية ، قد لا يزال هذا شيئًا ، لكنه يتعب بسرعة. وتذكر كل التلاعب في شهر أو شهرين.
ما هي خياراتك؟
توفر لنا الإنترنت والحكمة الشعبية ما يلي:
- حل مشكلة على مستوى المشروع. يمكن أن تكون تطبيقات هذا النهج مختلفة: المشاريع المنفصلة ذات الكود والأصول المشتركة ، والوحدات الفرعية في بوابة ، والفروع في بوابة وما شابه.
لا يمكنني التفكير بجدية في هذا. لسياج حديقة من أجل استبدال الرمز ، ومن ثم دعمه أيضًا. تماما الهواة. لكنه رأى ذلك بأم عينيه ، لذلك لم يستطع إلا أن أذكرها. - باش / الخفافيش / بيثون / ... مخطوطات.
بالفعل أكثر دفئا. ولكنه يتطلب معرفة إضافية ومن الصعب أن نسميها عبر الأنظمة الأساسية (غالبًا ما يتم تطوير جزء من الفريق تحت makos أو جزء من Windows). مرة أخرى ، تحتاج البرامج النصية إلى الدعم ، وهذا ليس هو الوقت المناسب دائمًا. - محرر البرنامج النصي في الوحدة نفسها.
حار جدا نحن ندير المشروع داخل الوحدة كما نريد. وإذا كنت تستخدم الأسلوب الثابت و BuildPipeline ، فيمكنك تكوين CI. كقاعدة عامة ، مقالات عن الوحدة و CI تصف ذلك. ومع ذلك ، لا يزال هناك عيب واحد في النهج السابق هنا: هذا هو الرمز ويجب كتابته وإضافته وصيانته. نحتاج إلى شيء مشابه ، ولكن دون الحاجة إلى كل نظام أساسي وتهيئة للدخول في الشفرة.
تم حلها. نكتب المساعد لدينا ، مع واجهة المستخدم والجنيات.
نحن بحاجة إلى خطة
تحتاج أولاً إلى تحديد ما نريد فعلاً الحصول عليه ولماذا.
- تخزين إعدادات المشروع لكل تكوين (هنا يمكنك الانتقال إلى مصطلحات البرنامج المساعد نفسه والاتصال بخياراتهم). ينصح بتنفيذ خيارات الميراث. على سبيل المثال ، بالنسبة لجميع التركيبات المستقلة ، ستكون إعدادات المشروع شائعة ، وستختلف الخيارات من بعضها البعض فقط في رمز المشروع واسمه. من المنطقي تمامًا حل هذا بالميراث ، بدلاً من لصق النسخ.
- تمثيل مرئي لما هو مختلف في تجسيد معين وكيف يختلف عن إعدادات المشروع الحالية.
- الجمع بين الخيارات في مجموعة. لتكون قادرًا على جمع مجموعة فرعية من البنيات باستخدام زر واحد أو طريقة ثابتة واحدة في وقت واحد.
- حزم البناء في الأرشيف. هذا مطلب اختياري. في حالة استخدام البرنامج المساعد جنبًا إلى جنب مع خادم البناء ، يمكن تنفيذ هذا العنصر من جانبه. لكنني أرغب في تبسيط الحياة لتبسيط كل شيء ، ولكن لا يوجد دائمًا خادم بناء.
- نقل الملفات في مراحل مختلفة من التجميع. على سبيل المثال ، تحتاج إلى استبدال بعض الأصول (الرمز ، البداية ، المشهد ، إلخ) قبل التجميع (يجب أن يكون استبدال الأصول في هذه الحالة قابلاً للانعكاس ، ويجب ألا يؤدي إنشاء الإنشاء إلى تغيير الحالة الحالية للمشروع). أو إعادة تسمية بنية Windows النهائية {exe_name} _Data إلى البيانات (سلوك وحدة مزعج للغاية ، بدون هذا التلاعب لا يمكنك إعادة تسمية الملف القابل للتنفيذ). أو مرة أخرى ، في تصميمات Windows ، رتب StreamingAssets اللازمة. تحتاج إلى القيام بذلك قبل تعبئة الأرشيف. ثم ، على سبيل المثال ، اسحب جميع الأرشيفات في مكان ما في مكان واحد.
- تحتوي مشاريع الوحدات على قدر كبير من الإعدادات ولا نريد مطلقًا كتابة واجهة المستخدم الخاصة بنا لجميعها. علاوة على ذلك ، فهو بالفعل في الوحدة نفسها. لذلك ، سوف نقوم بتغيير إعدادات المشروع كالمعتاد ، وفي المكون الإضافي نتابع التغييرات في الإعدادات ونحفظ في الخيارات الضرورية.
- أرغب في تخزين كل خيار في ملف منفصل بحيث يكون من الممكن سحبه بين المشاريع.
- من المستحسن العمل مع الوحدة منذ الإصدار 5.6. هناك بعض المشاريع القديمة مع الكثير من الضجة حول البنى.
حمامة
الجزء الرئيسي من البرنامج المساعد لدينا يعمل مع إعدادات المشروع ، وكذلك تخزين ومعالجة خيارات الإعدادات الفردية. لذلك ، سوف نركز على هذا.
تقوم الوحدة بتخزين جميع الإعدادات في دليل ProjectSettings في جذر المشروع. وأول شيء عند التهيئة سنقوم بحفظ هذه الإعدادات في دليل البرنامج المساعد (بالمناسبة ، هذا هو BuildVariants في جذر المشروع). هذا مطلوب حتى نتمكن من تتبع جميع التغييرات اللاحقة. بعد ذلك ، نحن بحاجة إلى تخزينها بطريقة أو بأخرى. الأسهل سيكون ببساطة نسخ ProjectSettings إلى موقع منفصل لكل خيار. وفي وقت تفعيلها ، فقط استبدالها كلها. الفكرة تعمل تمامًا وفي البداية فكرت فيها. لكن هذا يحرمنا تمامًا من فرصة وراثة الخيارات. وإذا كنا نكتب بالفعل مكونًا إضافيًا ، فسنقوم بذلك على الفور بشكل جميل. لذلك نحن بحاجة إلى تعلم القراءة والكتابة لمحتويات ProjectSettings.
للقيام بذلك ، تحتاج إلى فهم ما يتم تخزينه هناك. ويتم تخزين معظم الأصول العادية هناك ، والتي يتم تسلسلها وإزالتها بطريقة منتظمة. هذا يعني أنه يمكننا قراءتها من خلال AssetsDatabase والحصول على SerializedObject. هذا بالفعل شيء. نظرًا لأنه يمكننا متابعة جميع SerializedProperty ، تتبع خلافاتهم مع "لقطة" الأصلي وحفظها كمتغير. بعد ذلك ، عند تجميع أو تنشيط متغير ، نجمع التغييرات على طول سلسلة الميراث بأكملها ، ونطبقها على "اللقطة" وننزلقها في ProjectSettings. فويلا.
لكن SerializedProperty لديه بعض الميزات غير السارة: طريقة لتخزين القيم (كل هذه intValue ، floatValue ، isArray) ، عدم وجود آلية طبيعية لمقارنتها (هناك نوعان من الكائنات المرتبطة ، كيف نفهم ما إذا كانت جميع SerializedProperty لديهم نفس القيم) والمفارقة (وربما لا) عدم وجود سمة Serializable (مما يعني أننا سوف نحتاج إلى بعض المجمع لحفظ). لا يمكنني القول أن هذه بعض العيوب القاتلة ، كل هذا تم فعله أكثر من مرة في نصوص محرر عديدة. ولكن ما زلت أريد شيئا أكثر بساطة ومفهومة وعالمية.
أو ربما سنحد بشكل طفيف من استخدام البرنامج المساعد لدينا؟ دعها تعمل فقط على المشروعات ذات التسلسل النصي للأصول (هل يستخدم شخص آخر ثنائيًا؟). ثم سيتم تخزين جميع ProjectSettings كمستندات yaml. يمكنك استخدام مكتبة YamlDotNet واستخدامها لتحليل الإعدادات وحفظها. في الوقت نفسه ، قم بتخزين التكوينات الخاصة بك في yaml. لذلك أكثر وضوحا. تحتاج فقط إلى إضافة بعض الملحقات لفرق وثائق yaml والجمع بينهما.
توتر قليلاً مع نافذة المحرر (لا أريد حتى أن أصف ، آمل أن يصبح التعايش مع UIElements أسهل وأكثر متعة) ، وجمع كل شيء في كومة جاهز.
النتيجة
حان الوقت لإظهار ما فعلت . لقد تعرفت بالفعل على الآليات الرئيسية لعملية المكونات الإضافية ، وبالتالي ، فهي أطروحة أخرى حول بعض الميزات:
- تتم إضافة الخيارات إلى المجموعة المحددة باستخدام علامة اختيار على يسار الاسم.
- يجب تحديد مسار البناء بالملحق. لم أجد قائمة كاملة بالملحقات لجميع BuildTarget الممكنة ، لذلك تركتها حتى الآن.
- نقل الملفات موروث بنفس طريقة الإعدادات.
- لم تنفذ صفائف فرق. لذلك ، إذا قمت في الإصدار القديم بتغيير شيء ما في قائمة المشهد ، فسيتم استبدال القائمة بالكامل بالكامل. حسن النية تحتاج إلى الانتهاء.
- فرق المشروع الفعلي هو قائمة بجميع الاختلافات بين الخيار المحدد وإعدادات المشروع الحالية. علاوة على ذلك ، إذا تم تحديد الخيار النشط ، فيمكن التراجع عن التغييرات في الإعدادات الحالية.
- الإعدادات المتغيرة ، وفقًا لذلك ، هي تغييرات فردية في الخيار المحدد ، باستثناء التغييرات الأبوية.
- عند تنشيط الخيار ، سيتم فقد جميع التغييرات غير المحفوظة في إعدادات المشروع.
- إذا كانت هناك تغييرات لم يتم حفظها في إعدادات المشروع ، فإن أي محاولة لإنشاء البنية من خلال البرنامج المساعد ستنتهي بالتنفيذ. لأن انظر أعلاه ، وكما نتذكر ، يجب ألا يغير إنشاء البنية الحالة الحالية للمشروع.
- يمكن استخدام البرنامج المساعد مع خادم البناء. هناك طرق ثابتة لهذا: BuildVariants.Controller.BuildController.BuildAll و BuildVariants.Controller.BuildController.BuildCollection (مع اسم المجموعة في المعلمة -collection) و BuildVariants.Controller.BuildController.BuildVariant (باسم المتغير في المعلمة -variant). سيبدو شيء مثل هذا:
$unity_path -batchmode -projectPath $project_path -quit -logfile -executeMethod BuildVariants.Controller.BuildController.BuildCollection -collection standalone
- للأرشفة ، لدى البرنامج المساعد تبعية أخرى في شكل مكتبة DotNetZip.
- تمت كتابة المكوّن الإضافي في ظروف هدوء صغير في العمل ، لذلك لا توجد فرصة لاختباره وتخفيفه في معارك شرسة. قد يكون هناك أخطاء ، وربما حتى سيئة وغير سارة.
الخطط المستقبلية
بالطبع ، أريد إطعام ميزات المكون الإضافي إلى أجل غير مسمى ، ولكن حان الوقت للعودة إلى المشروعات الحقيقية ، وفي الوقت نفسه اختبار الوظيفة الحالية. بعد ذلك بقليل أريد تطبيق UIElements على الإصدارات الجديدة من الوحدة ، آمل أن يجعلها أكثر جمالا وملاءمة. وأود أيضا أن المسمار الإصدار وبعض ما يشبه متغيرات البيئة. ربما سيخبرك الجمهور بشيء آخر حول الوظيفة أو قابليتها للاستخدام.
لذلك ، سأكون سعيدًا بأي اقتراحات وتعليقات وأسئلة وتقارير الأخطاء. من السهل يبني لك!