post

ميزات 2019.3 Unity – الجزء الثاني

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

في هذا الفيديو سنقوم بالإكمال على الميزات التي تم إضافتها للمطورين Developers وكيف أنهم قامو بإضافة العديد من التحيسنات على الواجهة الرسومية للمحرك ، وتحسينات على آداء المحرك نفسه، بالإضافة إلى الحديث عن بعض الميزات التي أضافوها للمنصات الأخرى إن كانت للـ Mobile أو لل VR أو ال AR.

أدوات جديدة للمطورين

1 . تحسين عملية الـ Serialization

يبدو تبسيط البيانات واضحاً بعدما قدمت الشركة طرق جديدة في ال Serialization ، وبشرح بسيط فعلمية ال Serialization هي تحويل ال Objects إلى قيم أو نصوص يمكن تخزينها على القرص الصلب أو قواعد البيانات أو الذاكرة، فسابقاً كان يتم إضافة وسم [Serializable] لل Class وبالتالي كان المحرك يقوم بتحويله إلى قيم نوعية Value Type ، الآن أصبح بالإمكان إضافة وسم SerializeReference وبالتالي أصبح بالإمكان تحويل ال Classes إلى references ، هذا يعني أنه أصبح الآن بالإمكان ربط أكثر من كائن ببعض، الذي بدوره سيؤدي إلى تبسيط الكود لإدارة هيكلية بيانات معقدة مثل الـ graphs و الـ trees .

أيضاً تم إضافة مكتبة UnityYAML لتسريع عملية ال serialization خصوصاً في مرحلة تحميل المراحل. ويمكن تعريفها على أنها شيء مشابه لل JSON وهي طريقة تحويل ال Object إلى شيء يمكن كتابته على القرص الصلب أو الذاكرة.

2 . تسريع الدخول في Play Mode

قامت الشركة أيضاً بإضافة ميزة تجريبية قد توفر عليك ما يقارب 50% إلى 90% من وقت الإنتظار بعد أن تقوم بالضغط على زر Play لتجريب النتائج الجديدة الخالية من تعديلات الكود. فبواسطة خاصية Enter Play Mode التجريبية يمكنك تجاوز مرحلتين أساسيتين يقوم بهما المحرك. فسابقاً عندما تقوم بالضغط على زر Play كان المحرك يقوم بإعادة تهئية ال Codes بما يعرف بإسم Domain Reload كمرحلة أولى، وبإعادة تحميل المشهد Reload the scene كمرحلة ثانية، الآن بهذه الميزة التجريبية يمكنك بعد تفعيلها من إعدادات المشروع Project Settings تحت قائمة Editor بوضع علامة صح بجانب خيار Enter Play Mode ، يمكنك تقليل الوقت خصوصاً في المشاريع الضخمة.

3. تحسينات على الـ Profiler

في النسخ السابقة لنسخة 2019.3 عندما كنا نقوم بتحليل اللعبة بواسطة أداة الـ Profiler التي تقوم بإعطاء تفصيل دقيق لكل أقسام اللعبة لكشف مقدار السرعة في الأداء ومقدار الحجم في الذاكرة، كان سابقاً يقوم بعمل تسجيل لآخر 300 فريم، والتي كانت أحياناً غير كافية لإستخراج بيانات تفصيلية نريدها، في هذه النسخة تم إضافة ميزة لزيادتها من 300 فريم إلى 2000 فريم .

أيضاً تم إضافة ميزة Deep Profiling Support في حال كانت النسخة لمنصة PC Standalone حيث يمكن تسجيل الوقت عند إستدعاء أي دالة c# Methods ، طبعاً هذا الخيار مفيد جداً في عملية تحسين اللعبة وال Testing مع مراعاة أن تفعيل هذا الخيار سيعطي بطئ للعبة كونها ستقوم بالتسجيل أيضاً.

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

4. تحسينات على طريقة كتابة DOTS

كما ذكرنا في الجزء الأول من الميزات أن DOTS إختصار لـ Data-Oriented Technology Stack ، وهي من أكثر الأمور التي قدمت للمطورين فرص لتحسين ألعابهم، ففي هذه النسخة قامت الشركة بتقليص عدد الأسطر البرمجية لتحقيق الميزات السابقة، حيث أصبحت تستخدم C# Job System بالإضافة إلى Backend Compiled إسمه Burst Compiler حيث يعتبر مترجم متدني المستوى Low Level Virtual Machine ويقوم بتحويل أسطر لغة الـ C# إلى أسطر محسنة بلغة الآلة Machine Code .

5. تحسينات على ال Physics

بالبداية قامت الشركة بتطوير النسخة المستخدمة من PhysX المحرك مفتوح المصدر المطور من شركة Nvidia الخاص بالحسابات الفيزيائية، حيث تم تطوير المكتبة من نسخة v3.4 إلى v4.1 ، ويمكن الرجوع إلى صفحة المحرك لمشاهدة الأمور الجديدة التي تم إضافتها، من أهمها هي تقديم Solver جديد لربط ال Joint الخاصة بتحريك المجسمات وجعلها أقل عرضة لعمليات ال Stretch بالتفاعل مع المجسمات المحيطة، وتطوير خوارزمية سابقة لتصبح أكثر فاعلية في توليد المجسمات في وقت اللعب لتأخذ وقت وكلفة قليلة من مواصفات الجهاز، بالإضافة لأمور أخرى.

على صعيد آخر قامت شركة Unity بتقديم المحرك الفيزيائي الشهير Havok بنسخة متقدمة مبنية على تقنية ال DOTS حيث تعاونت الشركة المنتجة مع شركة Unity لإصدار هذه النسخة الحصرية، فهي متاحة فقط من خلال ال Package Manager وتحتوي على 3 باقات إحداها مجانية والباقي يأتي من ضمن ال subscription plans الخاصة لمحرك اليونيتي، ويجدر بالذكر أن محرك Havok مبني على native C++ حيث أنه يقدم نتائج سريعة ودقيقة لمن يهتمون بالدرجة الأولى بالفيزيائية في ألعابهم، وهي مناسبة جداً لأجهزة ال Consoles والموبايل.

أدوات المرئيات Graphics

1. نمط الإظهار المتقدم HDRP

إن كنت تطمح للإستفادة القصوى من المرئيات والإظهار المتقدم فعليك إختيار HDRP المختصر من High Definition Render Pipeline حيث أنه في هذه النسخة أصبح Verified بعدما كان تجريبي Preview ، فهو يقدم الجودة العالية للإظهار Rendering ، ويمكنك مشاهدة الفيلم الدعائي القصير المنتج من الشركة بعنوان ( The Heretic ) ، ففي نسخة 2019.3 أضافو إمكانية كتابة معالجة للصورة النهائية خاص بك بواسطة Custom Post-Processing ، بالإضافة إلى ميزة Physically Based Sky ، حيث أصبح بالإمكان الآن محاكاة الشمس والسماء الحقيقية بناءاً على الوقت، مما يتيح لك إلتقاط مشاهد نهارية أو ليلية جميلة.

أيضاً الآن بالإمكان تشغيل تقنية الواقع الإفتراضي VR مع الإظهار المتقدم HDRP للحصول على أقصى جودة تحاكي المشاهد الحقيقية، ويجب التنويه أن الإظهار المتقدم HDRP يستنزف موارد الجهاز لذلك ينصح بإستخدامه فقط مع الأجهزة المتطورة جداً high-end hardware.

ومن ضمن الميزات التجريبية الجديدة المضافة إلى HDRP ميزة real-time ray tracing features ، التي تعطي نتائج واقعية للضوء ولفيزيائية الضوء، فهي تقوم بحسابات الإنعكاس والظلال والإنكسار بالإعتماد على نوع المادة الساقط عليها الضوء، وهي تقدم أكثر ميزتين مطلوبتين وهما الـ global illumination والـ ambient occlusion بالإضافة للميزات الأخرى التي تحول الصور إلى حقيقة. التي كانت ولا تزال تحتاج إلى وقت تصيير طويل Long Time Render وإلى مواصفات جهاز عالية جداً، كما المصيرات Renderer المشهورة مثل ال Vray وغيرها.

2. نمط الإظهار المتوسط URP

نمط الإظهار المتوسط الـ Universal Render Pipeline أو ما كان يعرف سابقاً بالـ LWRP المختصر من Lightweight Render Pipeline هو نسخة مبسطة من نمط HDRP وهو أفضل من النمط التقليدي Default Render Pipeline ، حيث يأتي هذا النمط حالياً بشكل forward renderer حيث يقوم بحساب جميع الإضاءة في طبقة واحدة، وهو يدعم أنواع جديدة من الإضاءة في حال تم إستخدام 2D Renderer كما وضحنا في الجزء الأول من الميزات، وتم زيادة عدد الأضواء المسموح بها بهذا النمط إلى 256 ضوء في حال كان التطوير لغير الموبايل، أما الموبايل فتم زيادته أيضاً وهو يدعم 32 ضوء ، وهناك نسخة deferred renderer قادمة قريباً إليه.

المؤثرات البصرية Post-processing الآن تم تضمينها داخل النمط بعدما كان يتم إضافتها بشكل منفصل، حيث بإمكانك الحصول على تأثير تنعيم الأطراف ومانع التكسير anti-aliasing ، وتأثير التركيز بعمق depth of field ، وتأثير camera motion blur ، و Panini projection ، و bloom ، و lens distortion ، و chromatic aberration ، و color grading ، و tone mapping ، و vignette ، و film grain ، 8-bit dithering .

3. أداة Shader Graph

قبل الحديث عن أداة Shader Graph يمكننا التحدث أولاً عن أداة Visual Effect Graph، حيث يمكنك بشكل بصري أن تقوم بصنع نظام جزئيات Particle System معقد ومن صنع تأثيرات على مستوى الشاشة Post Processing أو حتى تأثيرات على واجهات اللعبة UI ، الضباب والمجسمات المضيئة وغيرها من التأثيرات التي تعطي إظهار أفضل Visual Effects كلها يمكن عملها داخل هذا المحرر. وفي هذه النسخة أصبحت هذه الأداة Verified بعدما كانت تجريبية Preview وهي تعمل الآن فقط مع النمط HDRP. ويمكنها التعامل مع أداة Shader Graph كما سنوضح الآن .

أما بالنسبة لأداة الـ Shader Graph ، فإنها ولا تزل مركز للتطوير كونها تفتح أفاق جديدة للمطورين ليقومو ببناء Custom Shader لكي يضعوه على المجسمات في داخل البرنامج، فقد قامو بإضافة vertex skinning لـ DOTS animation ، وأصبح هناك إمكانية لعمل العديد من النسخ static branches بعدما قامو بإضافة الـ Shader keywords ، أيضاً أصبح هناك إمكانية لعمل جمل ملاحظات Sticky notes داخل الـ Shader Graph للتوضيح لتساعد كل من يعمل معك في المشروع على فهم ما قمت بعمله.

4. تحسينات على أدوات الإضاءة

قامت الشركة أيضاً بعمل تحسينات على بعض الأدوات الخاصة بحسابات الإضاءة والظلال، فأصبح الآن بإمكانك دمج نفس الـ Light Probe بأكثر من مشهد الذين يعملون بطريقة المشاهد الترابطية additively loaded Scenes ، هذا يتيح للمطور تقسيم المرحلة الكبيرة إلى مشاهد Scenes صغيرة مترابطة مما يعطي فعالية أكبر للعبة، فبعد دمجهم وتحميل المراحل الصغيرة الجديدة يمكنك الحصول على نفس الحسابات السابقة بطريقة سلسة وبنتائج تعطي واقعية عالية، وتم تحسين حسابات الإضاءة فيها وتفادي بعض النتائج المزعجة سابقاً التي كانت تؤدي إلى ظهور Noise في المجسمات بسبب العدد الكبير للإضاءة.

على صعيد آخر، قامت الشركة بتحسين أداء حسابات الـ Progressive Lightmapper ، فحالياً هناك نوعين يمكنك بواسطتهما حساب خرائط الضوء Lightmap إما بالمعالج CPU أو بكرت الشاشة GPU ، فسابقاً كان التعامل مع ال Editor أثناء هذه الحسابات يعطي عدم أريحية للمطور حيث أنه يلاحظ وجود تقطيع كبير وقلة إستجابة بسبب العمل المستمر على حسابات الضوء، الآن أصبح الأمر أكثر إستقرارية وقابلية للتنقل والتعامل حتى أثناء الحسابات، بالإضافة إلى ميزات أخرى كلها تعمل بشكل أساسي على تقليل الوقت المستغرق وإعطاء نتائج مرضية والتقليل من الـ Noise الناتج أثناء عملية الحسابات.

واجهة المحرر، وأدوات العمل الجماعي

1. واجهة رسومية جديدة

من أهم الميزات الموجودة في هذه النسخة هي المظهر الجديد للمحرك، فقد قامت الشركة بإعادة تصميم كل الواجهة وكل الأيقونات الخاصة بكل شيء، وتغيير نوع الخط المستخدم ليتماشى مع دقة الشاشات الحديثة ويقلل التكسير الناتج من الواجهة القديمة. حيث قامت الشركة بالإستعانة بخبراء الـ UX المختصرة من User Experience لإعطاء راحة للعين وللمستخدم في تنقله في كل أقسام الواجهة الرسومية، التي شملت كل النوافذ الثابتة والمتحركة وكل المحررات الفرعية الداخلية.

وعلى غرار أغلب البرامج الكبيرة، تم الآن إضافة ميزة البحث السريع Quick Search من خلال الضغط على زر Alt + ` (حرف الذال ) والبحث مباشرة عن أي شيء داخل أو خارج المحرك، وهذا من هدفه تسريع عملية التطوير من خلال الإختيار السريع لما يحتاجه المطور أو المصمم.

2. محرر واجهات UI Builder

من أكثر الميزات التي جذبتني شخصياً هي أداة UI Builder ، فكل مطور يدرك تماماً مدى المشاكل التي تنتج بشكل دوري بواجهات اللعبة UI ، فمثلاُ ما أن تقوم بعمل زر في الشاشة وتقوم بتغيير دقة اللعبة إلا وتتغير جميع الواجهة التي قمت بعملها سابقاً، هناك حلول بسيطة يمكن إستخدامها سابقاً، لكنها لا تزال واحدة من أكثر الأمور المزعجة للمطورين والمصممين داخل المحرك، الآن أصبح هناك أداة منفصلة كليا ًويمكن تنزيلها من ال Package Manager تحت إسم UI Builder ، يمكنك من خلالها بناء واجهة رسومية جداً رائعة وجداً متفاعلة مع كل أقسام الشاشة، ليس هذا فحسب، بل يمكنك إيضاً التعامل مع ملفات CSS التي تقوم بإضافة Template لنمط معين ويمكنك إستخدامه للكثير من العناصر بضغطة زر واحدة. وهذه الأداة مخصصة للمصممين الذين يتقنون التعامل مع CSS و الـ UXML .

هناك أيضاً العديد من الأدوات التي قامت الشركة بتطويرها، فقامت الشركة بتحسين أداة ال Package manager نفسها، بدعمها لـ Git repository من خلال رابط، فضلاً عن إمكانية رؤية ال Assets التي قمت بشراءها أو تنزيلها مباشرة منه،

على صعيد العمل التشاركي، قامت الشركة بتطوير Unity Accelerator الذي من هدفه أن يقوم بسرعة عكس التغيرات من شخص بالفريق إلى كافة الأطراف الأخرى، بمعنى رؤية النتيجة التي يقوم بها المبرمج بشكل أسرع لدى باقي الفريق، أيضاً هناك Addressables الذي تسهل تنظيم جميع ال Assets المستخدمة من خلال مسارات معينة داخل اللعبة لإستدعاءها داخل المشروع من أي مكان بالكود، أيضاً قامت الشركة بتطوير AssetDatabase Pipeline من النسخة الأولى إلى النسخة الثانية، المهمة في عملية تنظيم جميع ال Assets الموجودة في المشروع.

المنصات Platforms

1. نظام الإدخال Input System

من أكثر الطلبات الملحة لدى المطورين هي إمكانية تغيير أزرار التحكم داخل اللعبة، فسابقاً كان يمكنك إختيار الأزرار فقط وقت التطوير، ولا يمكن تعديلها بعد أن تقوم بنشر اللعبة، مما كان يدفع البعض إلى شراء Assets مخصصة مبنية لنظام Input System جديد، الآن أخيراً تم حل هذه المشكلة مع أداة جديدة لازالت في وضع التجربة Preview ، وهناك العديد من الميزات التي أنصح بالإطلاع عليها.

أيضاً بهذه النسخة أصبحت أداة Incremental Garbage Collector مستقرة Verified ، الأداة المسؤولة عن إدارة الذاكرة وإزالة أي مجسمات لا حاجة للعبة بها، وأخيراً أعلنت شركة Unity عن دعمها لتصدير ألعابك لمنصة Stadia التي أعلنت عنها شركة Google قبل بضع سنوات.

أدوات أخرى

هناك العديد من المزايا الجديدة أيضاً التي لم يسعفنا الوقت للحديث عنها مثل AR Foundation ، وكيف قامت الشركة بتطوير وزيادة إنتاجية الواقع الإفتراضي VR والواقع المعزز AR ، وأيضاً أداة Device Simulator التي تتيح لك تجربة اللعبة على Emulator لرؤية النتيجة، والعديد من المزايا الأخرى التي يمكن الإطلاع عليها من صفحة الميزات الجديدة لدى الشركة.

إلى هنا نكون قد وصلنا إلى نهاية درسنا على أمل أن نلقاكم في درس جديد إن شاء الله.

post

ميزات 2019.3 Unity – الجزء الأول

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

تم إضافة الميزات للعديد من الاقسام الرئيسية، وسنتناول في هذا الجزء الأقسام التالية :
– التقسيم الجديد لنسخ المحرك، التجريبية وطويلة الأجل
– الأدوات الجديدة للفنانين والرسامين Artist and designers
– الأدوات الخاصة بالألعاب ثنائية البعد 2D Tools

على أن يتم الحديث عن الأقسام التالية في الجزء الثاني وهي:
– الأدوات الجديدة للمطورين Developers
– تحسينات الظهور Graphics
– تحسينات المحرك
– وإدارة المنصات

النسخ التجريبية، والنسخة طويلة الأمد

في البداية، قامت الشركة بتأكيد فصل المحرك إلى قسمين، القسم الأول يحتوي على المحرك الأصلي لوحده الـ Core ، والقسم الثاني هو Packages يتم إضافتها للقسم الأول، بهذه الخطوة يمكنك إستخدام نسخ مستقرة من المحرك أو ما أسموه LTS المختصر من Long-Term Support وإضافة أي مزايا جديده عليه مما يتم تطويره ما بعد إصدار تلك النسخة دون الحاجة لتجديد المحرك في كل نسخة مقبلة، فأي ميزة جديدة ستراها في هذه النسخة ستكون عبارة عن إضافة Package جديدة يمكن تنزيلها من ال Package Manager داخل المحرك، وهنا أيضاً قامو بتعريف النسخ الحديثة والتي تحتوي على نسخ تجريبية بـ TECH Releases حيث سيتم إصدار إثنتان منها كل سنة، على أن يتم إصدار النسخة المستقرة LTS مرة واحدة كل سنتين.

فيديو يشرح نظام النسخ المستقبلية من محرك الألعاب Unity

أدوات جديدة للـفنانين والمصممين

1. أدوات الأرضية Terrain Tools

يمكنك الآن صنع فجوات Hols وكهوف Caves في نظام الأرضية التابع للمحرك، الشيء الذي كان من أكثر الطلبات الملحة من قبل المصممين، حيث أنهم كانو سابقاً يضطرو لنمذجة مجسم الجبل والكهف بشكل منفصل عن Terrain مما كان يحتاج لكتابة أكواد خاصة بما يتعلق بالفيزيائية والأمور الأخرى، الآن أصبح بإمكانك بكل بساطة إختيار Paint Surface Mask tool ومسك الفرشاة والرسم على الـ Terrain كما لو كنت تقوم بتلوينها. والفجوات Holes ستتأثر بكل الأنظمة الأخرى مثل الفيزيائية والـ navigation mesh وحتى خرائط الضوء lightmapping التي ترتبط بشكل أساسي بمجسم الـ Terrain ، ويمكن للمبرمجين الوصول للفجوات والتحكم بها عبر custom terrain logic .

أداة Terrain Tools التي تسمح بصنع فجوات في الأرضية

أيضاً قامو بتحسين رسم التضاريس من خلال أدوات الرسم Terrain Material painting حيث قامو بإضافة 15 أداة للحفر على الـ Terrain لتعطي تفاصيل دقيقة وتقلل من الإعتماد على برامج خارجية قدر الإمكان، هذا كله يمكنك الحصول عليه بإضافة الـ Terrain Tools Package من الـ Package Manager .

أدوات فرشاة جديدة للرسم على الأرضية وإضافة تضاريس عالية الجودة

2. أدوات التحريك Animation Tools

تم إضافة أداة Animation Rigging التجريبية أيضاً إلى الـ Package Manager، حيث أنها تساعد وتسهل من عملية التحريك في الخط الزمني Timeline المخصص لعمل الحركة وهي موجة بشكل أساسي للأشخاص المسوؤلين عن التحريك Animators ، فهناك أدوات الدمج بين حركتين وإضافة الطبقات الخاصة بالتحريك Sequences and Layers لإنشاء حركات جديدة كلياً عن التي أتت عندما قمنا بإستيراد المجسم، والتي ترتبط إرتباط وثيق مع محرر الـ Rig Editor و ال Animation Window لتساعد المحركين من التقليل على إعتمادهم أيضاً على البرامج الخاصة بالتحريك خارج محرك الألعاب Unity.

أدوات منفصلة للمحركين Animator

3. الهئيات المُعَدّة مسبقاُ Presets

الآن أصبح بإمكانك تغيير الإعدادات الأولية default state لأي شيء في المحرك، سواءاً العناصر components او الإستيراد Importers أو حتى الـ Managers ، فمثلاً تريد كل مجسم جديد أن يمتلك خامة ذو لون أحمر بالإضافة إلى كود خاص يأتي عليه مباشرة بعد قيامك بإنشاء هذا المجسم، أصبح الآن من السهل عمله بدون كتابة أي سطر برمجي لذلك. الأمر الذي من شأنه تسهيل عملية التصميم ، وهو أيضاً يساعد في إتخاذ القرار بين تصميمين معينين، فبدلاً من عمل مشهدين بإعدادات مختلفة يمكنك بضغطة زر واحدة تغيير كل المجسمات إلى حالة معينة، وفي النسخة 2019.3 يمكنك عم أكثر من إعدادات أولية، بالتالي يمكن إعطاء مجسمات إعدادات مختلفة حسب إحتياج تصميمك.

تغيير الإعدادات الأولية لأي شيء يزيد من سرعة التصميم

4. خامات من برامج مختلفة renderer materials

في هذه النسخة أصبح بالإمكان الإعتماد على مكتبات خامات Material من خارج المحرك، فهناك الكثير من برامج التصميم التي تمتلك أنواع مختلفة من الخامات بما يتناسب مع البرنامج، وفي هذا النسخة 2019.3 أصبح بالإمكان إستيرادها والتعامل معها مباشرة، والتي ستظهر نتيجة متطابقة مع البرنامج الأصلي دون الحاجة لعمل خامات جديدة متقاربة في المحرك، وهذا يعطي إمكانية أكبر للمصممين على البرامج الأخرى من الإبداع أكثر في الخامات على برامجهم. والأنواع التي يتم دعمها الآن هي: Autodesk Arnold Standard Surface shader, Autodesk 3ds Max physical material, and the Autodesk Interactive shader.

أصبح بالإمكان إستيراد الخامات من البرامج الخارجية دون الحاجة لتعديلها

5. منع إختيار مجسمات معينة Scene Picking

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

إظهار وإخفاء المجسمات أصبح أسهل الآن

أيضاً تم إستبدال الـ grids القياسية بأداة أكثر إنتياجية إسمها ProGrids ، حيث يمكنك إختيار المحور الذي تود إظهار الـ grid عليه وقيمة الإنتقال أو الدوران Snap ، ويمكنك الحصول على هذه الأداة من خلال تثبيتها من Package Manager ثم ستجدها متاحة ضمن قوائم المحرك.

أداة ال ProGrids تعطي تحكم أكبر في موقع المجسمات

6. أدوات DOTS-powered للمصممين

لعل من أبرز ما جاء في هذه النسخة هي إحتوائها على أداتين موجهة للـ Designers تعمل بتقنية الـ DOTS ، و DOTS إختصار لـ Data-Oriented Technology Stack ، ويمكن توضيحها بشكل بسيط على أنها محاولة إستغلال الـ MultiCore Processors لإعطاء أداء خارق خصوصاً على أجهزة الموبايل، والتي تعطي سرعة عالية أيضاً في الحسابات والـ Frame Rate . الأداتان الجديدتان يمكن إضافتهما من خلال Package Manager تحت إسم Entities package ، وهي حالياً تجريبية Preview ، الأداة الأولى Conversion Workflow تقوم بتحويل المجسمات GameObjects إلى entities بضغطة واحدة، والأداة الثانية هي Unity Live Link ، حيث أنه أي تغيير داخل المحرك ينتج عنه تعديل في كل الأجهزة المتصلة معه. للمزيد من التفاصيل يمكن مراجعة الروابط في الأسفل.

أدوات DOTS سرعة خارقة في الأداء

الأدوات ثنائية البعد 2D Tools

في هذه النسخة أيضاً تم التركيز بشكل كبير على الألعاب ثنائية البعد فتم إضافة العديد من الأدوات التي تعطي جودة عالية وتأثيرات حقيقية، لذلك تم جعل الأدوات التالية مستقرة Verified :

1. مستورد ملفات الفوتوشوب 2D PSD Importer :

الآن أصبح بالإمكان حفظ ملف الفوتوشوب PSD إلى صيغة PSB وتصديره لمحرك Unity حيث سيقوم المحرك بأخذ جميع الطبقات Layers وبناءها على أنها مجسم واحد لكي تستخدمها في التحريك، وهذه الأداة جداً مفيدة وتحفظ الكثير من الوقت حيث يقوم المصمم بعمل الشكل الكامل للشخصية والمحرك يقوم بتقسيمها ضمنياً ويقوم بربطها معاً مرة أخرى.

نفس الشخصية في الفوتوشوب هي في المحرك

2. التحريك ثنائي الأبعاد 2D Animation :

أصبح الآن من السهل تحريك الصور ثنائية الأبعاد Skeleton 2D Sprite ، حيث بإمكانك إضافة Bones وإضافة وزن لك منها، وبالتالي عمل حركة متكاملة للشخصية، وتم تقديم كل الأدوات التي يحتاجها المحرك Animator لينتهي من الحركة كما لو أنه يقوم بها في برنامج خارجي.

عمل عظام لتحريك الشخصية بسهولة

3. أداة بناء المراحل وأداة تشكيل الصورة:

المحرك الآن يتحوي على أداتين مهمتين في بناء المرحلة أو ما يسمى بخريطة اللعبة World Map ، حيث أن الأداة الأولى هي 2D TileMap Editor ، وتقوم بأخذ مجموعة من الصور ثنائية البعد ورسمها لتبني خريطة لعبة كاملة، فمثلاً تقوم بعمل 3 صور واحدة للعشب وواحدة للتراب وواحدة للماء، وكل ما عليك هو إختيار إحداها وبدء الرسم على المحرك ليقوم هو بنفسه بضبط الصور وتركيبها معاً. والأداة الثانية هي 2D Sprite Shape ، حيث تفيد هذه الأداة في عمل خط طويل من صورة واحدة دون الحاجة لتكرارها في كل مرة، وايضاً يمكنك إختيار صور تقوم بملء الفجوة الداخلية بالتالي تحصل على شكل مناسب الذي إن قمت بعمله يدوياً سيأخذ منك الوقت الكثير عدا عن الدقة المطلوبة في حال كانت يدوية.

الرسم أصبح أسهل مع أدوات الصور ثنائية الأبعاد 2D Tools

4. دقة الصورة ذو النوع Pixel :

أيضاً هناك ميزة 2D Pixel Perfect التي تضمن أن الصور ذو النمط Pixel ستبقى حادة وبنفس حجمها في حالات تغير الدقة المستخدمة في اللعبة، مما يعطي الإنطباع الأصلي الذي يريده المطور.

الصورة تبقى كما هي في حالة دورانها أو تغيير الدقة

أيضاً لازالت الشركة تقوم بتطوير العديد من الأدوات التي يهتم بها مطور الألعاب ثنائية الأبعاد، فهناك تحسينات على الضوء وعلى الظلال المستخدمة من خلال إستخدام خريطة Normal Map ، وأيضاً قامو بإضافة عدد من الأدوات الجديدة مثل 2D Animation’s Sprite Swap التي تجعلك تقوم بتبديل صور من شخصية معينة مع الحفاظ على العظام وتركيبها دون الحاجة لعملها من جديد.

إدوات إضاءة وظلال للشخصية

نلتقي في الجزء الثاني إن شاء الله.

post

#22 مكتبات الدوال Namespace – البرمجة بواسطة #C

رمز فتح مرحلة هذا الدرس في تطبيق طورني : VVG

تَعلُمُ البرمجةِ للمبتدئينَ كلياً بواسطةِ #C – التعامل مع المكتبات Namespace

تحدثنا في الدروس الماضية كيف أن Microsoft قامت بكتابة العديد من الدوال التي من هدفها أن تقوم بتسهيل عملنا على المشاريع. كيف قامت Microsoft بتنظيم و تصنيف هذه الدوال ، و ما هي الـ Assemblies ، و ما هي دلالة كلمة using ؟ هذا ما سوف نتعرف عليه في هذا الدرس ان شاء الله .

ما هي ال Assembly Code Files؟

كما تحدثنا في المقدمة فإن Microsoft قامت ببناء و كتابة آلاف من الدوال التي من هدفها أن تساعدنا في مشروعنا ، فكما لاحظنا و كثيراً استخدمنا دالة Consloe.WriteLine . WriteLine هي دالة لكتابة شيء على الشاشة ، هذه الدالة تمت كتابتها بواسطة Microsoft.

الشيء الذي نود توضيحه هنا هو أنه في كل مرة نقوم بإنشاء مشروع جديد يقوم المحرر باستدعاء الدوال التي تهمنا في هذا المشروع ، فمثلا عندما نقوم بعمل مشروع Console نجد أنه يستخدم بعضا من الـ References الموجودة على اليمين ،حيث نجد مثلا System , System.Core , System.Data ,System.Net.Http و غيرها .. ، هو فعليا يقوم باستدعاء هذه المكتبات ، و هذه المكتبات يمكن أن نبسطها على أنها ملفات Code Files تسمى Assemblies.

هذه الـ Assemblies قامت Microsoft بتقسيمها لأقسام كثيرة ، لأنه تخيل أن تقوم باستدعاء كافة المكتبات التي تكلمنا عنها – والتي تعتبر بمئات الآلاف من الـ Functions – ، فليس من المنطق أن تقوم باستدعاء كل هذه المكتبات ، لأنه أولا سينتج بطؤ شديد في التطبيق ، بالإضافة إلى أن كل الدوال ستخزن في الـ Memory الخاصة بالجهاز، و بالتالي لن يستطيع التعامل مع أي شيء آخر.

إذاً Microsoft قامت بتقسيم هذه الملفات إلى أقسام معينة ، و الجميل في الموضوع أنه كل مرة نقوم بكتابة Method داخل الـ Application الخاص بنا فإنه يمكننا إعادة تحويلها إلى Assembly ، حيث أننا إن شاء الله سنتعلم في الدرس القادم كيف يمكننا تحويل الـ Method التي قمنا بكتابتها إلى ملفات dll لكي نستخدمها في مشاريع أخرى مستقبلية .

ما هي دلالة كلمة Using؟

إذاً أنا قمت بفتح مشروع جديد Console و أسميته AssembliesAndNamespaces ، و بإمكانكم إيقاف الفيديو و الذهاب لعمل مشروع جديد ، قمت بكتابة سطرين فقط ، Console.WriteLine و Console.ReadLine . و لاحظو أن هذا النوع من المشاريع “الـ Console” يستدعي كما تكلمنا قبل قليل مجموعة من الـ References يمكن أن نجدها هنا في القائمة الموجودة على اليمين .

و من أهم الـ References المستخدمة في هذا المشروع هو الـ System ، و أحيانا من ضمن هذه الـ Libraries يتواجد أسماء Methods تتشابه مع أسماء Methods موجودة في كلاسات أخرى ، و لكي نقوم بحل هذه المشكلة يجب علينا أن نقوم باستدعاء الـ namespace الأصل الخاص بهذه الـ Method .

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

ذات الأمر في الكود الخاص بنا هنا ، فعندما نقوم باستخدام الـ namespace الكامل الخاص بالـ Method ، ثم كتابة الـ Method نكون قد قمنا بالحد من التضاربات الموجودة. فعندما ننظر هنا إلى الكود ، سنجد أن دالة Console موجودة في الـ namespace الذي اسمه System . و عند تعديل الكود ليصبح :

System.Console.WriteLine(“…”);

سأكون استدعيت الـ namespace الخاص بـ Console ، و استخدمتها مباشرةً ، نلاحظ أن الكلمة System أصبح لونها رمادياً ، و هذا يعني أنه يمكن الاستغناء عن الكلمة ، و لا يشترط أن أقوم بكتابتها. لأننها قمنا في الأعلى بكتابة :

using System;

و بذلك نكون قد أخبرنا التطبيق أنه “أي Method تابعة للـ namespace المسمى System ، قم باستخدامها مباشرة ، دون الحاجة لكتابة الـ namespace الخاص بها في كل مرة”.
فمثلا لو حذفت الـ 5 اسطر الأولى الموجودة في الأعلى ، سنجد مباشرة أن السطر رقم 9 :

System.Conole.WriteLine(“…”);

قد تحولت الكلمة System من اللون الرمادي إلى اللون الأبيض ، بمعنى أنه يجب استخدامها الآن
كما سنلاحظ ظهور خطأ في السطر العاشر . Console.ReadLine();

و قمنا بعمل Run للـ Application سنجد أن البرنامج تم تنفيذه بشكل صحيح دون مشاكل .

إذا للحد من الحاجة لكتابة الـ namespace في كل مرة نقوم باستخدام الكلمة using و هنا نكتب using System ، و عند كتابتها من جديد ستعود الكلمة System في السطر رقم 9 و 10 إلى اللون الرمادي ، بمعنى أنه ليس من الضروري كتابتها .

الكتابة على ملف File :

لنأخذ الآن مثالاً جديداً على كيفية استخدام Library خارج نطاق الشيء الذي نعمل فيه ، فمثلا في حالة الـ Console الشيء الذي نحتاجه هو الـ System ، و لكن ماذا لو أردنا كتابة text معين في ملف .
هنا يجب أن نستدعي Library الخاصة بعملية الكتابة على الملفات ، سنذهب إلى المتصفح للحصول على مثال موجود مسبقاً لنكتب في Google ” How to write to a text file C# ” سنلاحظ الكثير من النتائج التي ستظهر لدينا ، من بينها مجموعة الصفحات الخاصة بـ Microsoft ، و سنجد في هذه الصفحة 3 طرق للكتابة على file ، لنأخذ المثال الثاني هنا .

        // Example #2: Write one string to a text file.
        string text = "A class is the most powerful data type in C#. Like a structure, " +
                       "a class defines the data and behavior of the data type. ";
        // WriteAllText creates a file, writes the specified string to the file,
        // and then closes the file.    You do NOT need to call Flush() or Close().
        System.IO.File.WriteAllText(@"C:\Users\Public\TestFolder\WriteText.txt", text);


نلاحظ في السطر رقم 14 أنه يقوم باستخدام namespace اسمه System.IO لكي يستدعي الـ File و الدالة التي تقوم بكتابة النص على الـ File .
سنأخذ القسم System.IO و نقوم بوضعه في الأعلى إلى جوار الكلمة using ليصبح

Using System.IO;

ثم قمنا بحذف القسم من الدالة في الأسفل ، سنلاحظ عدم ظهور أي مشكلة ، و بالتالي يمكننا التعامل مع الدالة بدون مشاكل ، سأقوم بتغيير الـ path للـ File لنرى الناتج الذي سيظهر على الملف ، إذا عندما أقوم بعمل تشغيل للبرنامج ، و أذهب إلى المسار الذي وضعته هنا سأجد أنه قام بكتابة النص الموجود في المتغير text على الملف النصي .

تحويل صفحة إنترنت إلى نص وتخزينه

لنأخذ مثالاً آخر لكيفية عمل تنزلي لصفحة إنترنت و تحوليها إلى text و كتابته على الـ File ، لنذهب إلى المثال الآخر ، و الموجود أيضاً على صفحة Microsoft (C) ، يمكنكم البحث عن “How to download HTML as string” ، سنجد مثالاً في الأسفل ، لنأخذه و نضعه في المحرر الخاص بنا ، سنجد مثالاً في الأسفل ، لنأخذه و نضعه في المحرر الخاص بنا :

public static void DownloadString (string address)
{
    WebClient client = new WebClient ();
    string reply = client.DownloadString (address);

    Console.WriteLine (reply);
}

نلاحظ بمجرد عمل لصق للمثال ، يظهر لدينا مشكلة ، و ذلك لأن النوع WebClient غير معرف لدينا ، حيث أن الـ Compiler لم يقم بالتعرف على هذه الكلمة . و إذا وضعت مؤشر الماوس على الكلمة ، ستجد أن الـ namespace غير موجود ، و نلاحظ ظهور مصباح ذو لون أصفر أسفل الكلمة ، و بالضغط عليه سيعطينا خيارات لإصلاح هذه المشكلة ، نلاحظ أنه قام بتقديم حلين ، إما أن تقوم بكتابة using System.Net; أو أن تقوم بكتابة الـ namespace كاملاً في هذا السطر.

لنتفادى المشكلة سنقوم بعمل إضافة using System.Net; في الأعلى ، و ذلك بالضغط على الاقتراح الذي قام البرنامج بتقديمه. و عندها ستصبح باللون الأخضر ، و ذلك دلالة على أنها أصبحت معرفة لدى الـ Compiler .

سنقوم الآن باستبدال كلمة Address بالرابط الذي نريد نسخه ، و سنقوم بكتابة الناتج على الـى File
و عندما نقوم بتشغيل التطبيق ، و نذهب إلى الملف سنلاحظ أنه قام بطباعة كامل الصفحة كـ HTML

إذاً تعرفنا في هذا الدرس كيف يمكننا استخدام كلمة using ، و كيف يمكننا استدعاء أي Method نريد استخدامها سواء بكتابة الاسم الكامل لها أو كتابتها في القسم الأول (استدعاء المكتبات أو الـ Assemblies التي نريد استخدامها ) في مشروعنا .

post

صناعة الأفلام داخل محرك Unity

الأدوات التي يتيحها المحرك لصناعة الأفلام

أصبح محرك الألعاب يونيتي أداة قوية لإنتاج الأفلام، فأصبح هناك تحكم كامل بحركة الكاميرا وال Textures و تحريك المجسمات، هذا كله بشكل مباشر داخل نافذة عرض المحرك، بالإضافة إلى التغيير الآني لإعدادات الإضاءة ، ومشاهدة النتيجة مباشرة دون الحاجة إلى الإنتظار لرؤية النتيجة، يمكنك الآن نمذجة وتحريك المجسمات داخل المحرك بواسطة Pro Builder ، إيضاً لازال هناك إمكانية أخذ المجسمات من خارج المحرك من برامج التصميم المشهورة مثل 3ds max أو maya وغيرها. من خلال تصدير المجسمات بصيغة FBX.
بمجرد الإنتهاء من المجسمات، يمكنك عمل حركة لها بسهولة بواسطة محررات المحرك timeline sequencing tool ، وبعد ذلك يمكنك ببساطة سحبها ووضعها في المكان الملائم لها داخل المشهد.

أداة تحكم الكاميرا Cinemachine

أما بالنسبة للكاميرا، فهي المكان التي يبدأ فيها فيلمك بالحياة، فبواسطة أداة Cinemachine يمكنك تحديد نقطة المركز بحيث تتحرك تلقائياً بما يتناسب إبقاءها في المشهد، وتعطيك تحكم كامل بحيث يمكنك دمج اللقطات مع بعضها بسهولة ، وهذه تعتبر من أهم ميزات محرك اليونيتي، حيث لا حاجة بعد الأن لإضاعة أو إعادة صناعة اللقطات بسبب عدم ملائمة لقطة معينة، كل ما عليك فعله هو تحريكها ببساطة لتشاهد النتيحة مباشرة أمامك، وميزة ال Cinemachine أنها تعطيك تحكم كامل في ال Frames حيث بإمكانك تقديمها أو تأخيرها بما يتلائم مع مشهدك، أيضاً هناك تأثيرات ال Post Processing التي تعطي تأثيرات على الصورة النهائية فيمكنك إستخدام ال depth of field أو أي تأثير من التأثيرات المتعارف عليها بين منتجي الأفلام.

الإضاءة المباشرة والغير مباشرة

لم تكن إضاءة الأفلام أسهل إطلاقاً قبل التعرف على محرك يونيتي، فإختصاصي الضوء يقضي وقت كبير للحصول على النتيجة المرضية، بالإضافة إلى أنه يقضي وقت كبير للإنتظار للحصول على النتيجة التي ستعطيه القرار بالمضي قدماً أو بالتعديل مرة أخرى، هذا كله تم الإستغناء عنه مع محرك الألعاب يونيتي، فالأن يمكنك تغيير الإضاءة وتعديلها ورؤية النتيجة النهائية مباشرة من خلال نافذة المحرك، فال Material المعقدة والظلال يتم تصييرها آنياً ، ومن خلال تغييرات بسيطة تستطيع الحصول على النتيجة المرضية لك ، فمثلاً تغيير شدة الإضاءة أو إتجاهها أو لون الإضاءة ونوعية الظلال الناتجة منها كله يتم مباشرة من خلال إعدادات يمكن إختيارها.
بالعودة إلى الكاميرا فهنا يمكنك تغيير إعدادات الإضاءة مباشرة من خلال عرض النتيجة بين ما تشاهدة الكاميرا وبين ما تود إضافته للمشهد ، أيضاً يمكنك إستخدام ال Post Processing لتغيير الإضاءة الكلية للصورة، ويمكنك إستخدام distortion motion blur grain and vignette ، وغيرها من التأثيرات.
أيضاً من أدوات اليونيتي إداة ال VFX Graph ، حيث يمكنك عمل particle معقدة من خلال نظام عقد Node-Base System .

أداة Shader Graph

أما بالنسبة إلى النتيجة النهائية للمجسم لوحده، فهناك العديد من الأدوات التي يمكنك إستخدامها لتحسين شكل ال Character أو ال Props المتناثرة داخل المشهد، فيمكنك إستخدام ال Shader-Graph لعمل نتائج مذهلة من خلال دمج عناصر معينة للحصول على نتيجة مرضية، وشاهد آنياً بعد كل تعديل النتيجة بتأثرها بهذا ال Shader ، أيضاً ال Shader Graph يمكنه أخذ ال Shaders التي قمت بعملها من البرامج الأخرى مثل substance designer وغيرها،
أيضاً من خلال هذه الأداة يمكنك عمل الفرو Fur ، فحركة الفرو ووزنه يتم التحكم بهما من خلال خرائط ال height maps و ال groom maps التي تم عملها داخل برنامج substance painter وبرنامج Mari ،
ولا يكتمل شكل الشخصية من غير تأثير الإنعكاس الموجود على العين، فهنا أيضاً تم عمل Shader خاص لإنعكاس الضوء وال ambient occlusion المخصص والمعروف للعين، كل هذه الميزات وغيرها، تعطي النتيجة النهائية للفيلم ككل، يمكنك بكل بساطة أن تقوم بتغيير أي شيء في أي وقت تريده، بسرعة وأداء عالي،
Sherman هو مشروع مفتوح، يمكنك مشاهدته وتنزيل ملفاته من الروابط التالية :

فيلم شيرمان : https://www.youtube.com/watch?v=JFtCHvyul-I
ملفات العمل للتنزيل : https://on.unity.com/2K1PZ4O

post

تضمين إعلانات Admob داخل Unity

سنأخذكم في هذا الدرس في جولة سريعة لنتعرف معاً كيف نقوم بوضع الإعلانات في ألعابنا ، سواء كانت للـ Android أو لـ IOS ، فنحن كما نعلم أن الإعلانات حالياً هي اكثر مصدر للدخل في الألعاب، و هناك العديد من المزودين الذين بإمكانك بواسطتهم عرض الإعلانات داخل لعبتك ، و سنقوم في هذا الدرس ان شاء الله بالتعامل مع google AdMob

تهئية وعمل حساب على Admob

في البداية هناك أمور يجب أن تكون موجودة مسبقاً ، ألا و هي حساب AdMob ، و إذا لم تكن تمتلك حساب AdMob ، يمكنك بسهولة التوجه إلى admob.google.com و عمل حساب جديد ، بعد عمل حساب جديد ستحصل على واجهة جديدة ، بإمكانك من هذه الواجهة من خلال قائمة الـ Ads إضافة اعلان جديد ، و يجب أن نعلم أنه في كل الإعلانات يجب فصل الـ Android و الـ IOS ، فمثلاً إذا أردت عمل إعلانات لنسخة IOS يجب أن تمتلك ID مختلف عن الـ ID الخاص بنسخة الـ Android ، بعد الضغط على new Ad سيسأل هل اللعبة موجودة على متجر Google Play أو IOS ، سوف نختار لا . في الصفحة التالية سيطلب كتابة معلومات عن اللعبة ، سنقوم بكتابة اسم اللعبة ،و نختار نسخة اللعبة ، (IOS / Android) و سنختار في هذا الفيديو Android و نضغط Add

أهم شيء هنا هو الـ App ID ، بإمكاننا الذهاب إلى App settings و سنجد الـ App ID ، الخطوات موجودة في الرابط https://developers.google.com/admob/unity/start بشكل مرتب ، لاحظ أنه يتطلب منك خطوات متعددة مثل انشاء حساب AdMob

إضافة دوال Admob إلى Unity

يجب أن نقوم بتحميل Mobile Ads Unity plugin ، الذي يحتوي على المكتبة الخاصة بعملية Show Ads و هو موجود في الرابط السابق ، نضغط تحميل و سنجد أن الباقة موجودة و قابلة للتحميل هنا :
https://github.com/googleads/googleads-mobile-plugins/releases/latest

و من Unity سأقوم بالذهاب إلى Assets > Import Package > Custom Package ، و نختار الباقة التي قمنا بتحميلها و نقوم بعمل import لكل شيء ، ثم نقوم بعمل resolve ، نذهب إلى Assets > Play Services Resolver > Android Resolver > Resolve ، عندها ستظهر رسالة تخبرنا باكتمال دمج الباقة ، الآن أصبحت الـ APIs و المكتبة التي تدعم Google جاهزة و متاحة للتحكم ، يتبقى علينا أن نقوم بتغيير الـ Application ID الخاص بنا في منطقة معينة ، Assets/Plugins/Android/GoogleMobileAdsPlugin ، سنجد الملف AndroidManifest.xml ، نضغط الزر الأيمن للماوس و نختار show in explorer ، ثم نقوم بعمل تحرير للملف لتعديله ، نقوم بنسخ الـ App ID السابق و لصقه في مكانه كما هو مذكور في البند android:value ، ثم نقوم بحفظ الملف ، الآن بعد أن قمنا بعمل هذا ، يتقبقى أن نقوم بتفعيل عملية الضغط أو اخراج و عرض الفيديو

<manifest>
    <application>
        <!-- Your AdMob app ID will look similar to this
        sample ID: ca-app-pub-3940256099942544~3347511713 -->
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="YOUR_ADMOB_APP_ID"/>
    </application>
</manifest>

تفعيل مكتبة Admob وتهيئتها داخل Unity

نعود إلى الـ Documentation السابق ، نلاحظ أنه يتبقى علينا عمل Initialize للـ Mobile Ad ، نلاحظ أن لدينا 3 أنواع و الإعلانات و هي Banner / Interstitial / Rewarded
– الـ Banner يكون موجوداً طيلة وقت اللعب ، في أسفل أو أعلى الشاشة
– الـ Interstitial يقوم بعرض إعلانات عندما يتنقل اللاعب من واجهة إلى واجهة أخرى (تحميل المستوى أو العودة إلى الصفحة الرئيسية …. الخ)
– الـ Rewarded ، و يقوم بعرض فيديو ، و يتوجب على اللاعب مشاهدته كاملاً ليحصل على الجائزة ،و لا يحتوي على زر اغلاق للفيديو .
في البداية سنتعامل مع النوع Rewarded ، سأذهب إلى حسابي على AdMob ثم إلى Ad units سنقوم بـ create ad unit ، سيطلب اختيار نوع الإعلان ، سنختار Rewarded . في الشاشة التالية يطلب الاسم ، سنكتب أي شيء ، ثم نضغط Create ad unit. نلاخحظ أنه قام بعرض الـ Ad Unit ID ، نعود إلى الـ Documentation ثم إلى Implement rewarded ads لمعرفة كيفية استخدامه
في البداية يجب إن نقوم بعمل Initialize للـMobile Ads فنأخذ الكود ، من اليونيتي سنذهب إلى مجلد الـ Scripts و نقوم بعمل سكريبت جديد ثم نقوم بوضع الكود الذي قمنا بأخذه ، و لاننسى استبدال الـ App ID بالـ ID الخاص بنا ، الان سنقوم بسحب هذا السكريبت و وضعه على أي شيء ليتم تنفيذه مباشرة عند البدء ، الإن بمجرد الضغط على زر play لن يظهر شيء لأننا لم نقم ببرمجة شيء بعد ، و لكن إذا اذا ذهبنا إلى الـ Console سنجد أنه قام بعملية Initialize و هنا لا يوجد أي مشكلة ـ و هذا يطمئننا أن امورنا صحيحة ولا يوجد مشاكل ، بقي علينا أن نقوم بجعل الزر يجعلنا نشاهد الإعلان ، سنعود إلى ال Documentation مرة أخرى ، ثم إلى قسم الـ Rewarded ، لنشاهد كيف يمكننا إظهار الإعلان ، و نلاحظ هنا أننا سنقوم بتعريف متغير من النوع rewarded بحيث أن نقوم بعمل Initialize للـ adUnitId الذي سنستخدمه بعد قليل ، سنأخذ هذا المتغير و هذا السطر ، نلاحظ بعد الـ Initialize الـ Unit ID التي نحصل عليها من صفحة الـ Ad units

ضرورة التجربة بإعلانات Google وليس بإعلاناتك

هنا يوجد قضية علينا الانتباه إليها ، نلاحظ هنا في Google يقول “always test with test ads” ، هذا الكود الموجود هنا سيعرض فيديو من شركة Google ، فعندما تقوم بتجربة الإعلانات لا تضع الكود الخاص بك لأن هناك سياسة في الشركة تمنع المطور من استخدام الإعلانات ، و كأنه يقوم بعرض إعلانات لنفسه ليكسب المال ، و اذا قمت باستخدام كود على جهازك كمطور و قمت بعرض الإعلانات على جهازك ، فهناك إمكانية لعمل lock لحسابك ، و نحن لا نريد هذا الشيء ، إذا سوف نأخذ هذا الكود و نقم بلصقه ، بعد أن نقوم بعملية الاسناد للـ ID نقوم بعمل Request ليقم بعرض الإعلان ، إذاً بعد إضافة الكود الأخير يجب أن نقوم بعمل دوال تفيد في عمل ال Callback للـ Events ، فعندما ينجح أو يفشل الإعلان أو عندما يحصل شيء معين ، يقوم بتفعيل أو استدعاء هذا الـ event ، سنذهب إلى الـ Documentation ، سنجد أنه يوجد العديد من الدوال الموجودة مسبقاً ، سنقوم بأخذها و وضعها في السكريبت الخاص ، بعد أن قمنا بتصحيح الأخطاء ، إذا قمنا بتعريف الـ Rewarded Ads بهذا الـ ID الخاص بـ Google ، و الذي سيعرض لنا شيء خاص بـ Google و ليس اعلاناتنا ، طبعا عند الانتهاء ستقوم باستبداله بشيء خاص بك ، لاحظوا أنه عندما يتم استدعاء الكود بشكل صحيح سيقوم بإظهار الفيديو ، هنا لدينا عندما يتم تحميل الفيديو من الانترنت ، يجب أن نقوم بعمل عرض للفيديو ، فهو يقوم بالتحميل فقط ، فيجب أن نضع جملة شرطية ، عند نهاية التحميل قم بعرض الفيديو ، سنقوم بالحفظ و نعود إلى يونيتي ، بالضغط على زر شاهد سيظهر معلومات أنه لا يوجد أي مشكلة
لزيادة عدد الـ coins التي يكسبها المستخدم نذهب للدالة HandleUserEarnedReward ، في هذه الدالة اللاعب قام بمشاهدة الفيديو كاملاً فيجب أن نقوم بإعطائه coins ، هنا قمنا بتعرف المتغير coins
نذهب إلى build and run لنقوم بتشغيل اللعبة ، نلاحظ أن الـCoins عددها 0 ، بالضغط على الزر شاهد سيقوم بعرض الفيديو، و عند الانتهاء سيقوم بإضافة الـ Coins ، نقوم بالضغط مرة أخرى على الزر شاهد و نقوم بإغلاق الفيديو و نلاحظ أنه لن يقوم بمنحنا الـ Coins ، فيجب على اللاعب انهاء الفيديو ليحصل على الجائزة ، هذا كان بشكل سريع عن كيفية إضافة الـ AdMob داخل اللعبة على محرك الألعاب Unity

الأسطر البرمجية المستخدمة في هذا الدرس

using GoogleMobileAds.Api;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GoogleAds : MonoBehaviour
{
    private RewardedAd rewardedAd;


    // Start is called before the first frame update
    void Start()
    {
#if UNITY_ANDROID
        string appId = "ca-app-pub-3062555098484328~2649488225";
#elif UNITY_IPHONE
            string appId = "ca-app-pub-3940256099942544~1458002511";
#else
            string appId = "unexpected_platform";
#endif

        // Initialize the Google Mobile Ads SDK.
        MobileAds.Initialize(appId);
        
        

    }

    public void ShowAds()
    {
        this.rewardedAd = new RewardedAd("ca-app-pub-3940256099942544/5224354917");

        // Called when an ad request has successfully loaded.
        this.rewardedAd.OnAdLoaded += HandleRewardedAdLoaded;
        // Called when an ad request failed to load.
        this.rewardedAd.OnAdFailedToLoad += HandleRewardedAdFailedToLoad;
        // Called when an ad is shown.
        this.rewardedAd.OnAdOpening += HandleRewardedAdOpening;
        // Called when an ad request failed to show.
        this.rewardedAd.OnAdFailedToShow += HandleRewardedAdFailedToShow;
        // Called when the user should be rewarded for interacting with the ad.
        this.rewardedAd.OnUserEarnedReward += HandleUserEarnedReward;
        // Called when the ad is closed.
        this.rewardedAd.OnAdClosed += HandleRewardedAdClosed;


        // Create an empty ad request.
        AdRequest request = new AdRequest.Builder().Build();
        // Load the rewarded ad with the request.
        this.rewardedAd.LoadAd(request);
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public void HandleRewardedAdLoaded(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleRewardedAdLoaded event received");
        if (this.rewardedAd.IsLoaded())
        {
            this.rewardedAd.Show();
        }
    }

    public void HandleRewardedAdFailedToLoad(object sender, AdErrorEventArgs args)
    {
        MonoBehaviour.print(
            "HandleRewardedAdFailedToLoad event received with message: "
                             + args.Message);
    }

    public void HandleRewardedAdOpening(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleRewardedAdOpening event received");
    }

    public void HandleRewardedAdFailedToShow(object sender, AdErrorEventArgs args)
    {
        MonoBehaviour.print(
            "HandleRewardedAdFailedToShow event received with message: "
                             + args.Message);
    }

    public void HandleRewardedAdClosed(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleRewardedAdClosed event received");
    }

    public void HandleUserEarnedReward(object sender, Reward args)
    {
        GameLogic.coins += 150;

        string type = args.Type;
        double amount = args.Amount;
        MonoBehaviour.print(
            "HandleRewardedAdRewarded event received for "
                        + amount.ToString() + " " + type);
    }


}

post

#21 التغليف Encapsulation – البرمجة بواسطة #C

رمز فتح مرحلة هذا الدرس في تطبيق طورني : RSJ

تَعلُمُ البرمجةِ للمبتدئينَ كلياً بواسطةِ #C – التغليف Encapsulation

ما معنى Encapsulation ؟ و كيف يمكننا حماية اسطر برمجية معينة من التحكم بها و من القراءة بها ؟ ما هي درجات كلمات private و public ؟

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

Public void DoSomething()
{

}
Private void HelperMethod()
{

}

في الدالة الـ private سنقوم بطلب طباعة Hello world! ، و في الدالة الـ public سوف نقوم باستدعاء الدالة الـ private
الآن لدي في التطبيق الخاص بي عندما أقوم بتعريف متغير أو object من النوع something
Something s1 = new Something();
لاحظوا إذا كتبت s1 و قمت بالضغط على dot سيعطيني الدالة التي اسمها DoSomething و ليس لدي إمكانية التعامل مع الدالة HelperMethod لأن هذ شيء خاص و داخلي لا يمكنني الوصول إليه، الآن لو تابعنا
S1.DoSomething();
Condole.ReadLine();
و حاولنا تشغيل التطبيق سنلاحظ أنه سيقوم بطباعة الجملة الموجودة في HelperMethod

إستخدام التغليف لتطوير التطبيق

من الممكن أن نرغب بمعرفة عدد ضغطات المستخدم أو معرفة ما قام الزبون باستدعائه ، هنا سنقوم بتعريف متغير من النوع int باسم clickCount ، و نقوم بجعلها في الدالة private
clickCount ++;
لتعتبر الزيادة ، مثلاً عندما يقوم بعمل شيء معين أو يستدعي أداة معينة يزداد هذا العداد بدون معرفة الزبون ، فهو أمر غير مهم بالنسبة له ، كل ما يهتم به هو النتيجة النهائية ، أما أنا كمطور قد يهمني معرفة هذه الأمور و ربما أرغب بعمل تحليل للبرنامج الخاص بي
هناك أنواع أخرى غير public و private و هي protected و internal ، و هما متقدمين على هذه الدورة ، و بإمكانك البحث عنهما بشكل موسع
هذا كان بشكل سريع شرح لدرس اليوم encapsulation و نلقاكم في درس قادم إن شاء الله

الأسطر البرمجية التي قمنا بتنفيذها في هذا الدرس

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PrivatePublic
{
    class Program
    {
        private static string k = "";
        static void Main(string[] args)
        {
            Something s1 = new Something();
            s1.DoSomething();
            Console.ReadLine();
        }
    }

    class Something
    {
        static int clickCount;
        public void DoSomething()
        {
             HelperMethod();
        }
        private void HelperMethod()
        {
            Console.WriteLine("Hello World!");
        }
    }
}

post

#20 النطاق Scope – البرمجة بواسطة #C

رمز فتح مرحلة هذا الدرس في تطبيق طورني : BVP

تَعلُمُ البرمجةِ للمبتدئينَ كلياً بواسطةِ #C –  النطاق Scope

لماذا عندما نقوم بتتعريف متغير جديد ، لان نستطيع استخدامه في كل التطبيق ؟ ما هو الـ scope ؟ و ما هو النطاق الخاص بالمتغير ؟ و متى ينتهي المتغير و يتم حذفه من الذاكرة ؟

في درس اليوم سوف نتكلم عن النطاقات Scopes و أهميتها ، و ذكرنا سابقاً أننا سنقوم بشرحها مستقبلاً بشكل مكثف ، لدينا الآن برنامج Visual Studio 2019 Community و هو مجاني كما ذكرنا سابقاً، بإمكاننا عمل مشروع جديد من خلال Create new project و نقوم باختيار الـ Console app ثم الضغط على next و في الصفحة التالية نقوم بكتابة اسم مشروع ، و ليكن UnderstandingSscope ، سيفتح لنا النافذة الرئيسية للكود

الشيء الذي نريد إيصاله أنه عندما نقوم بتعريف متغير جديد ، فإنه سيكون متاحاً في القطعة البرمجية الموجود فيها حصراً ، أو كل القطع البرمجية الموجودة داخلها . و قد تكلمنا سابقاً أن القطعة البرمجية هي القطعة المحصورة بين القوسين { } ، سنقوم الآن بعمل حلقة for loop

 for (int i=0 ; i<10 ; i++)
 {
      Console.WriteLine(i.ToString());
 }
 Console.ReadLine(); 

فهم النطاق

اذا قمنا بتنفيذ المشروع ، فسنرى أنه قام بطباعة الأعداد من 0 إلى 9 كما هو المعتاد ، لكن لنلاحظ التالي ، لو قمنا بأخذ الجملة Console.WriteLine(i.ToString()); و كتابتها خارج القطعة البرمجية الموجودة فيها ( أي خارج القطعة الخاصة بالحلقة for loop ) ، يصبح الكود بالشكل :

 for (int i=0 ; i<10 ; i++)
 {
      Console.WriteLine(i.ToString());
 }
 Console.WriteLine(i.ToString());
 Console.ReadLine(); 

فنلاحظ أنه مباشرة سيظهر لدينا خطأ في قائمة الأخطاء ، و يقول الخطأ ، “the name does not exist in current context” ، بما معناه أن المتغير لا يمكن التعرف عليه في هذه المنطقة لأن الـ i حصراً لتلك القطعة البرمجية لأنها داخل نطاق الحلقة التكرارية ، بالتالي فإنه فعلياً غير موجود في القطعة البرمجية الأخرى ، و لن يتم التعامل معه .
سنقوم بجعل الجملة الخاطئة جملة تعليق . و سنقوم بعمل متغير جديد باسم j في القطعة الأولى ، و التي تحتوي على الحلقة for loop و نقوم بإسناده داخل القطعة البرمجية التابعة للحلقة for loop ، ثم نقوم بكتابة الجملة لتقوم بطباعة المتغير j خارج الحلقة for loop ليصبح الكود كالتالي :

{
     string j =” “ ;
     for (int i=0 ; i<10 ; i++)
     {
          Console.WriteLine(i.ToString());
          j = i.ToString();
     }
     // Console.WriteLine(i.ToString());
     Console.WriteLine(“j = “ + j.ToString());
     Console.ReadLine();
}

ثم نقوم بتنفيذ البرنامج … نلاحظ أنه يخبرنا في النهاية أن j تحصل على القيمة 9 ، نلاحظ أنه قمنا بتعريف المتغير j في القطعة الخارجية .. إذا لن يحدث أي خلل سواء استعملته في القطعة الداخلية أو في نفس القطعة التي قمت بتعريفه داخلها .

النطاق على مستوى ال Class

سنقوم بتعريف property جديدة من النوع String
Private static string k =” “ ;
و في الداخل ستكون قيمة k الجديدة ستكون هي قيمة i ، و سنقوم في الخارج بطباعة قيمة k الجديدة كما قمنا بطباعة قيمة j سابقاً ، بتنفيذ البرنامج نلاحظ أنه يعطيني نفس النتيجة النهائية . الشيء الذي نريد توضيحه أنه بحال قمت بتعريف method على مستوى الكلاس ، مثلا :

static void HelperMethod()
{
    K = “10” ;
}

و قمنا باستدعاء الـ HelperMethod في الأعلى ، ثم قمت بتنفيذ المشروع ، نلاحظ أن القيمة النهائية هي 10 ، لأن المتغير k على مستوى الكلاس ، فيمكنني استخدامه في أي منطقة داخل الكلاس ، و أنا قمت باستخدامه داخل method لأقوم بالتعديل عليه ، أيضا في جملة التكرار for سأقوم بوضع جملة شرطية ، في حال كان قيمة i هي 9 قم بتعريف متغير ، string l =” “ ; ، ثم نقوم مباشرة بطباعة هذا المتغير خارج اقواس الحلقة for loop ، مباشرة سيعطيني أن هناك خطأ … فهذا المتغير تم تعريفه في قطعة برمجية داخلية ، فهذا المتغير عندما يصل إلى نهاية القوس سينتهي و يختفي من الذاكرة ويكون خارج النطاق فلا يمكن استخدامه خارج هذه الاقواس . اذاً هناك نطاق لكل متغير ، ولا يمكن استخدامه خارج هذا النطاق ، و هذا الكلام ليس محصوراً فقط للمتغيرات ، فعندما نقوم باستنساخ مجسم من كلاس ، ينطبق عليه كل ما قمنا بتطبيقه في هذا الدرس ، هذا كان بشكل سريع ملخص لمفهوم النطاقات scopes .
نراكم ان شاء الله في درس قادم قريباً . السلام عليكم .

الأسطر البرمجية التي قمنا بتنفيذها في هذا الدرس

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace UnderstandingScope
{
    class Program
    {
        private static string k = "";
        static void Main(string[] args)
        {
            string j = "";
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(i.ToString());
                j = i.ToString();
                k = i.ToString();

                if (i == 9)
                {
                    string l = "";
                }
                //Console.WriteLine(l);
            }
            //Console.WriteLine(i.ToString());
            Console.WriteLine("j = " + j.ToString());
            HelperMethod();
            Console.WriteLine("k = " + k.ToString());
            Console.ReadLine();
        }

        static void HelperMethod()
        {
            k = "10";
        }
    }
}

post

لمحة حول ميزات 2019.2 Unity النسخة التجريبية

السلام عليكم ورحمة الله وبركاته ، طرحت شركة unity تسخة تجريبية للإصدار الجديد لمحركها لعام 2019 تحت رقم إصدار 2019.2 ، حيث قامت بذكر أهم الأجزاء التي سيحتويه والتي ستكون مضمنة في النسخة النهائية من الإصدار، حيث سيحتوي الإصدار على الكثير من التحسينات والإضافات الجديدة مثل تحسين الأداء لأجهزة المحمول، وإضافة أداة Polybrush وتسهيل نشر اللعبة على متاجر متعددة بواسطة The Unity Distribution Portal للوصول إلى عدد أكبر من اللاعبين، وتحسين الإضاءة وأدوات الواقع الإفتراضي والمعزز وغيرها الكثير.
يمكن تنزيل النسخة التجريبية من خلال Unity Hub البرنامج المسؤول عن التحكم في النسخ الموجودة في جهازك، مع الأخذ بالحسبان أن هذه النسخة التجريبية قد تحتوي على مشاكل تقنية معينة، حيث تطرح الشركة النسخة ليقوم المطورين بتجريبها وإيجاد أي مشكلة فيها لحلها قبل الإعلان النهائي عن النسخة المستقرة منها.
هنا ذكر لأهم الميزات لهذه النسخة :

تحسينات للأجهزة المحمولة


قامت الشركة بالتعاون مع فريق من شركة Google بتقديم تحسين للألعاب لتبقى على Frame ثابت وهو ما يعرف بإسم Frame Pacing ، وذلك بجعل الفرق بين عدد ال Frames المحسوبة أقل. والنتيجة كانت الحصول على smoother gameplay experience .


بالإضافة إلى ذلك تم تقديم إمكانية تفتيح الشاشة من خلال الخاصية Screen.brightness ، وقامو بإضافة تحديد لحجم الشاشة التي يمكن عرض اللعبة عليها من غير قص منها من خلال خاصية Screen.cutouts ، وهذه الميزة ستكون مفيدة مع الهواتف الجديدة مثل Samsung S10e .

تم إضافة أداة Polybrush


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

مزايا جديدة في إضاءة الـ 2D


تم تحديث وتطوير نظام الإضاءة Lightweight Render Pipeline (LWRP) ، حيث تم إضافة 2D Pixel Perfect وإضافة أنواع إضاءة خاصة بالمجسمات ثنائية الأبعاد، وتم إضافتها أيضاً إلى الـ Shader Graph الخاص بها. وقد تم تفصيل هذا المزايا في مؤتمر GDC 2019


تحديثات الإضاءة


الميزة الخاصة بإزالة ال Noise وبما يعرف بال Denoise الآن أصبحت تعمل على كل الكروت، حيث سابقاً كان بعض الأنواع تعاني منها وبعضها لا يعاني، ايضاً تم تغيير طريقة حساب خرائط الضوء Lightmaps ، حيث بإمكان أي مجسم موجود في المشهد المشاركة في حساب الإضاءة الغير مباشرة global illumination bake ، وتم زيادة سرعة الحسابات خصوصاً إذا تم إستخدام كرت الشاشة في ذلك.

صورة توضح الفرق بين ال Denoising وعدمه
الميزة الجديدة لتفعيل المجسمات من إستقبال الحسابات الخاصة بالإضاءة


أما بالنسبة لتحديثات خرائط الضوء بواسطة كروت الشاشة فهي أصبحت تمتلك الآن :
1 – أكثر من Importance Sampling support لإضاءة المحيط
2 – أصبحت تدعم NVIDIA OptiX denoising
3 – زيادة سرعة الحسابات عندما تستخدم النوع view prioritization او للمجسمات الصغيرة


متاجر عالمية لزيادة اللاعبين


أصبحت يونيتي تدعم بعض المتاجر العالمية لتساعدك بنشر ألعابك عليها وهي ما يعرف بإسم The Unity Distribution Portal (UDP) ، حيث تم التعاقد من بعض المتاجر الكبيرة التي تنافس جوجل ستور وأبل ستور مثل : Catappult/Aptoide, MOO Store, ONE Store, Jio Games Store
مع العلم أن جميع هذه المتاجر تعمل على نظام Android فقط، بمعنى أنك في حال قمت بتطوير لعبة للأندرويد يمكنك ببضع خطوات أن تقوم بإنزال لعبتك على المتاجر المذكورة


AR Foundation


في هذه النسخة هناك العديد من الميزات التي تم إضافتها مثل : face-tracking, 2D image-tracking, 3D object-tracking, and environment probes


هناك العديد من الميزات الأخرى التي يمكنك مشاهدتها في الرابط الأصلي للإعلان عن النسخة هنا :
https://blogs.unity3d.com/2019/05/09/unity-2019-2-beta-is-now-available/

post

لمحة حول ميزات 2018.1 Unity النسخة التجريبية

السلام عليكم ورحمة الله وبركاته ، طرحت شركة unity تسخة تجريبية للإصدار الجديد لمحركها لعام 2018 تحت رقم إصدار 2018.1 ، حيث قامت بذكر أهم الأجزاء التي سيحتويه والتي ستكون مضمنة في النسخة النهائية من الإصدار، حيث سيحتوي الإصدار على الكثير من التحسينات والإضافات الجديدة مثل نظام التفاصيل الزائدة Tessellation for Metal و إستحدام كرت الشاشة في الإضاءة غير المباشرة GPU Instancing ، إضافة منظور ال PS4 لنافذة Game Resolution وتحسينات على نظام الجزئيات Particle system والتحسين على بلجت التصدير FBX وغيرها الكثير. وهنا ذكر لأهم الميزات لهذه النسخة :

* نظام تصيير جديد  Scriptable Render Pipeline

حيث قدمت الشركة في هذه النسخة نظام إظهار آني real-time rendering ذو الإختصار SRP ، حيث أنه تم تصميمه خصيصاً لمواكبة الأجهزة الحديثة وكروت الشاشة السريعة جداً ، فبدلاً من النظر إلى ملايين أسطر البرمجة بلغة السي ++ أصبح الآن بالإمكان التعامل معه بواسطة لغة السي شارب و عمل شيدرز سريع للمواد Material Shaders بسهولة. حيث ستقوم الشركة بوضع أنظمة جاهزة Templates تستطيع من خلالها إختيار طريقة العرض التي ستلائم مشروعك بتقسيمين : Lightweight  حيث سيكون مثالي لأجهزة الموبايل والأجهزة الخفيفة و High-Definition حيث سيكون ملائم للمواصفات العالية جداً مثل أجهزة الحاسوب وغيرها.

* أداة visual shader creation

حيث تم تطوير هذه الأداة خصيصاً للمصممين والرسامين ، فبواسطة هذه الأداة يمكنك عمل مواد معقدة من خلال طريقة ال Graph Nodes  ،  فبدلاً من كتابة Shaders خاصة بواسطة الأسطر البرمجية أصبح بإمكانك عمل Shader كامل بواسطة ربط ال Nodes ببعضها لتحصل على الشكل النهائي الذي تريده ، وهذه الميزة كانت من أكثر الميزات طلباً من جمهور المطورين وتم الإستجابة لهم من الشركة .

* قريباً C# Job System

تحسينات وتطويرات ستكون متاحة قريباً تزيد من كفاءة اللعبة خاصة لمن يقوم بكتابة الأسطر البرمجة بلغة السي شارب

* تعديل على المواصفات الدنيا System Requirements

قامت الشركة بحذف العديد من الأمور التي كانت ضمنياً متاحة داخل المحرك وذلك بهدف جعل المحرك أكثر مرونة، وتركت باب الحصول على الميزات السابقة متاحة بتنزيلها منفصلة عن المحرك ، فقد قامت بفصل إمكانية إستيراد مواد Substance Designer materials وفصل Wii U  و فصل Windows XP in standalone player و فصل محرر MonoDevelop حيث أنها تنصح بإستخدام فيجوال ستوديو من شركة مايكروسوفت ، وقامت بزيادة مواصفات macOS إلى النسخة 10.11 على الأقل ، وهي تعمل على فصل نظام الجزئيات التقليدي  Legacy Particle System في النسخة القادمة وإستبداله بنظام جديد

يجدر بالذكر أن النسخة هي نسخة تجريبية ويمكنك تنزيلها والمشاركة بها من خلال هذا الرابط : https://unity3d.com/unity/beta

 

 

post

#19 مواضيع متقدمة عن Classes – البرمجة بواسطة #C

رمز فتح مرحلة هذا الدرس في تطبيق طورني : MRE

تَعلُمُ البرمجةِ للمبتدئينَ كلياً بواسطةِ #C –  مواضيع متقدمة حول الفئات Classes

مواضيع متقدمة حول الفئات Classes :

ما هو الـ Garbage Collector ، و ما هي دلالات كلمة  new التس نستخدمها عند الاشتقاق من الكلاس الرئيسي ، ما هي الـ Static ، و ما هو الـ Constructer الدالة التي تقوم بتنفيذ أسطر برمجية عند الاستنساخ من كلاس رئيسي ؟

هذا كله سنتعرف عليه في هذا الدرس بعد الفاصل إن شاء الله .

 

السلام عليكم و رحمة الله و بركاته ، و أهلاً و سهلاً بكم في درس جديد من دروس سلسلة تعلم البرمجة للمبتدئين كلياً بواسطة السي شارب

بسم الله الرحمن الرحيم ، في الدرس الماضي تحدثنا عن مدخل إلى البرمجة كائنية التوجه OOP و التي هي اختصار لـ Object Oriented Programming ، و تعلمنا كيفية بناء Class ، و التي  أصبحنا نعلم أنه يمكن ترجمة الـ Class إلى العربية بكلمة ” الفئة ” ، و تكلمنا كيف يمكنك بناء فئات أو Classes تحوي معلومات مشتركة ، و رأينا كيف يمكننا تعريف الـ Property  و رأينا كيف يمكننا استنساخ Object من هذا الـ Class

في هذا الدرس سنتكلم إن شاء الله عن أمور و تطبيقات إضافية للـ Classes و الـ Method نفسها ، و سنتكلم عن مفهوم الـ Object نفسه ، فما هو مفهوم الـ Object عندما نقوم باشتقاقه من الـ  Class ، و كيف يتم تخزينه و استدعائه ، و ماهي حلقة الوصل بينه و بين الذاكرة ، سيتم مناقشة هذا في القسم الأول من الدرس ، و سنراجع معاً ما هو دور الـ Dot Net Runtime في عملية إدارة الذاكرة .

 

تكلمنا في البداية أن الـ Dot Net له أقسام معينة و هو مسؤول عن تحويل أمور معينة و تعرفنا على Common Language Runtime و اختصارها CLR ، حيث سنأخذ فكرةً عنها ، و كيف ستساعدنا هذه الأمور في انتاج برامج قوية قادرة على إدارة الـ Data  ، و قادرة على إدارة عمل البرنامج بشكل افضل .

و سنتكلم أيضاً عن شيء يسمّى Constructer  ؛ و هو Method خاصة يتم استدعاؤها عندما يتم استنساخ Object من الـ Class ، و سنتكلم أيضاً عن معنى كلمة Static ، و التي رافقتنا من أول درس إلى هذا الدرس .

 

كالعادة نقوم بإنشاء مشروع جديد بلغة c# من النوع Console App

في الدرس الماضي تكلمنا عن المكان المناسب لتعريف الـ Class ، حيث قلنا أنه يجب أن يكون موازياً للـ Class الرئيسي ، في المنطقة الواقعة داخل الحافظة الرئيسية namespace  ؛ و التي تحتوي على مجموعة من الكلاسات .

 

في البداية هناك قضية أودُّ التنويه لها ، و هي إمكانية كتابة Class ضمن كلاس آخر ، أو ما يعرف بالـ Nested Class ، لكننا لن نتعمق في هذا الموضوع ، و سنتعلم الـ Class بمفهومه البسيط ، و الذي يمكن استخدامه في أي مكان .

إذا لكتابة Class جديد نذهب لأي منطقة موازية لأي كلاس آخر ، و يمكن كتابة الـ Class فوق الكلاس الرئيسي أو تحته ، فلا مشكلة في هذه النقطة ، إذا سننتقل إلى السطر رقم 15 ، و أقوم بكتابة نفس الـ Class الذي تعاملنا معه في الدرس الماضي .

لاحظوا أن هذا الـ Class المسمّى Car يحتوي على 4 خصائص ، كل منها لديه نوع خاص ، فالشركة المصنعة لديها النوع string و سنة التصنيع من النوع int .

اشتقاق Object من Class معين :

و لاشتقاق Object من هذا الـ Class تعرفنا أنه يمكننا كتابة اسم الـ Class الرئيسي أولاً ، ثم نقوم بتعريف متغير جديد myCar على سبيل المثال ، ثم وضع إشارة المساواة ، ثم new ثم اسم الكلاس مرة أخرى ، مع وضع اقواس () و الفاصلة المنقوطة ، حيث قمنا هكذا بجعل هذا الـ Object مستنسخاً من الـ Class الذي اسمه Car ؛ لاحظوا في هذه الجملة قمنا بتعريف متغير نستطيع أن نقول عنه أنه Object من النوع Car ، و لاحظوا أنه عندما قمت بوضع كلمة new فهناك عمليات موجودة خلف هذه الكلمة .

 

ما معنى كلمة new ؟

عندما تقوم بعملية استنساخ أو بناء مجسم جديد ، فأنت فعلياً قمت بربط هذا المجسم و معلوماته بمكان معين في الذاكرة ، Address  معين في الـ Memory ، و هذا المكان في البداية هو مكان فارغ عندما قمنا بكتابة Car myCar ، و لكن عندما قمنا بكتابة new Car قمت بإضافة المعلومات الأساسية التي يتكون منها هذا الكائن ، فعندنا في البداية كائن قمنا بتعريفه فارغاً و لكن عندما قمنا بعملية ربطه بكلمة new قام فعلياً بعملية انشاءه و تهيئته بالشكل الذي قمنا بكتابته في الـ Class ، و سنتعرف بعد قليل على ميزة خاصة بعملية الـ new Car الموجودة هنا .

يمكن أيضا تشبيه هذا الموضوع بالبالون ، حيث نفترض بالون معين يطير في الهواء ؛ هذا البالون له خيط ، هذا الخيط هو عبارة عن الـ myCar ، و هو اسم المتغير  ، أما المعلومات الموجودة به فهي موجودة على البالون ، فالمتغير يدل على المنطقة في الذاكرة التي تحتوي المعلومات الكاملة .

 

القضية التي نودُّ شرحها هنا أنه بإمكاننا كما تعرفنا في الدرس السابق ، بإمكاننا إضافة المعلومات الموجودة بداخله ، حيث نضيف معلومات اللون و الخصائص السابقة ،

يمكننا أيضاً إضافة Object آخر من نفس النوع Car و جعله يشير إلى نفس المكان الموجود في الذاكرة ، بمعنى … سنقوم بإضافة متغير جديد باسم myOtherCar ، و لاحظوا أنني في هذه الجملة قمت بتعريف Object لكنه فارغ ، لا يشير إلى مكان في الذاكرة ، أو ليس له محتويات يشير إليها ، فإن قلت له في السطر التالي ، myOtherCar = myCar ، ففعلياً في هذا السطر جعلت الـ Object يشير إلى المكان الذي يشير إليه myCar

نعود لمفهوم البالون لتوضيح الصورة أكثر .

لدينا البالون الذي اتفقنا سابقاً أن له خيطاً و اعتبرناه myCar ، بالجملة التي كتبناها قمنا بعمل خيط آخر ، و الذي هو myOtherCar و الخيطين يشيران إلى نفس البالون ، و لاحظوا أنني لم أقم بإسناد أي قيمة للمتغير ، بل جعلته مساوياً للـ Object السابق .

بمعنى أنني إذا قمت بعمل طباعة الجملة التالية ، فعندها سيقوم بطباعة Black ، على الرغم من أنني قمت بطباعة myOtherCar  و ليس myCar ، إذا فعليا في المتغير myOtherCar قمت بالإشارة إلى نفس البالون الذي يحمله الـ myCar و لتتأكدوا أكثر أن الاثنان مرتبطان بنفس المنطقة في الذاكرة ، سأقول له
;”myOtherCar .color = “Red
أنا فعلياً هنا قمت بتغيير اللون لـ myOtherCar و ليس myCar ، و سأقوم مباشرة بطباعة myCar.color
و للتوضيح باختصار : انا قمت بتعريف متغير myCar و قمت بوضع اللون الأسود له ، ثم قمت بتعريف Object آخر من النوع Car و قمت بإسناد موقع الـ myCar إلى myOtherCar ، و قمت بتغيير myOtherCar.color ،و سأقوم بطباعة الـ myCar الأولى ، عند التشغيل سيظهر Red المعدلة و ليس Black ، لأنه كما ذكرنا أنه عبارة عن مكان موجود في الذاكرة و هناك أكثر من خيط يشير له ، فأي تعديل على أحدهما يؤثر على الآخر ، فـ myCar و myOtherCar هما عبارة عن خيوط للمكان المحجوز في الذاكرة نفسه .

 

ماذا لو أردت أن أقطع هذا الخيط ، بمعنى أريد فصل myOtherCar عن المكان الذي قمت بتعريفه في الأعلى . بمعنى أن تنفصل myOtherCar عن myCar ، فأنا أريد جعلها تشير إلى مكان آخر في الذاكرة ، فعلياً في السطر 17 أنت تعرف خيطاً فقط لا يشير إلى شيء ، و لا يوجد معلومات به ، و لا نعرف كيف سيكون و ما هي محتوياته ، لذلك يوجد جملة myOtherCar = null هذه القيمة null فعلياً فارغة ، و بذلك في السطر 20 قلت له أن يقوم بفصل myOtherCar عن أي شيء آخر ، و اجعله فارغاً لا يحوي أي شيء ، و بذلك ، و بدءاً من هذا السطر لو قمت بعملية طباعة أي معلومة من معلومات  myOtherCar فسنلاحظ أنه سيظهر مشكلة و خطأ برمجي ، و هو : myOtherCar was null  أي أنه فارغ !! و لا أعرف ما هو الـ color الذي تريده ، و لذلك لا اعرف كيفية طباعة هذه الجملة ، و بالتالي يظهر الخطأ .

إذاُ .. فعليا في السطر 20 قمت بقطع الحبل الخاص بـ myOtherCar الذي كان يربطه بالبالون ؛ و عند هذا السطر ، فقط myCar هو الذي يحتوي الوصلة للبالون .

 

إذا قمت بعد ذلك بقص الخيط الثاني  و ذلك بجعل myCar  تساوي null أيضاً ، و لاحظوا أنني هنا بعد تعريف الـ  Object و اضافته أن هناك بالون معين و يحتوي على المعلومات القيمة التي أريدها . و بعد السطرين 20 و 21 قمت بقطع الشريطين ، و طار البالون في الهواء و المعلومات فعلياً ذهبت إلى الأعلى و انفجرت !!

إذاً القضية التي أريد أن اوضحها لكم أن في هذه الخطوات هي فعلياً عملية ربط Object معين بموقع ، و عندما تقوم بفصله ، أو عندما يصل إلى نهاية الـ Block الذ تم تعريفه داخله فإنه فعلياً يصبح null  أي فارغاً بغض النظر عن السطرين 20 و 21 .

 

هنا يأتي دور Dot Net Runtime فماذا يفعل ؟؟

هناك معلومات قيمة و معلومات كثيرة ، فنحن الآن نتكلم عن كلمتين أو خمس حروف و هكذا ، و لكن ماذا عن المشاريع الكبيرة ، عندنا كم هائل من الـ  Data و هذه البيانات إذا بقيت في الذاكرة و لم يتم التحكم بها ، فسيكون هناك مشاكل كبيرة نحن بغنى عنها ، و هنا يأتي دور الـ Dot Net Runtime  و الذي قلنا سابقاً أن اختصاره هو CLR سيقوم بالتالي :

ستذهب و تبحث في جميع الأكواد التي قمنا بكتابتها في هذا البرنامج ، و ستجد أن هناك بالون فارغ لا يوجد أي وصلة له ، و تقوم بالبحث إن كان هناك خيوط مرتبطة بهذا البالون أم لا ، و فعلياً لن تجد أي وصلة له ، و تقول : ” أنت يا بالون خارج  التغطية و لا أريدك ، سأقوم بتهيئة مكانك ، قم باستخدامه لمتغير آخر استفيد منه خلال البرنامج ”

إذا هذا الموضوع الذي يقوم بحذف و إدارة الذاكرة شيء يسمى Garbage Collector ، هو شيء خاص بـ CLR ، و يقوم بالبحث عن المناطق أو الـ Object  التي تم فصل الارتباط بها ، و يقوم بتهيئتها لاستخدامها بشيء آخر ، هذا المصطلح يجب أن تكونوا على اطلاع عليه ، و نحن عندما نقول أن لغة السي شارب هي لغة managed  يعني أنه يوجد شيء وسيط بينك و بين الآلة يقوم بإدارة أمور معينة أنت في غنى عنها ، و لكن لاحظوا أننا عندما نقول عن لغة السي و السي بلس بلس هي لغة unmanaged  ، فإنك عندما تقوم بالتعامل مع هذه اللغات فأنت مضطر لمتابعة المتغيرات و الذاكرة و مواضيع أخرى ، فأنت مجبر أن تقوم يدوياً بعمل تفرغ لكل Object  قمت بالانتهاء منه ، كي لا تحدث مشاكل في الذاكرة و حجم البرامج ، و مشاكل كبيرة أنت في غنىً عنها .

لماذا اخترنا السي شارب ؟؟
لأنها لغة managed ، حيث توفر لنا إمكانيات و أدوات نحن في غنىً عن الغوص في تفاصيلها ، فنحن نريد أن نركز على فكرة التطبيق الذي نريد عمله

 

الآن في السطر رقم 13 عند تعريف Object  جديد قمت باستخدام قوسي الدالة () ، الحقيقة هنا يتم استدعاء  Method داخل الكلاس حتى و إن لم تقم بكتابتها و تعريفها ، ألا و هي دالة الـ Constructer  ، و هي دالة يتم استدعاؤها عندما تقوم بعمل initialize  للـ Object ، بمعنى أنه عندما تقوم بعمل فتح و اغلاق قوس يتم تنفيذ شيء معين ، و فعلياً هنا لأننا لم نقم بكتابة شيء ، هو قام بمناداته ، و لكنه ضمنياً فارغ .

لكي نتعامل مع هذا الموضوع و نتعرف عليه أكثر ، سنقوم الآن بالتعرف على كيفية كتابة الـ constructer  .

شكلها كالتالي :

()public Car

{
}

و اسمها طبق الأصل مع اسم الكلاس ..
هذه الأسطر من 29 إلى 32 ضمنياً موجودة ، و لكنها فارغة ، طالما قمت بكتابتها ، فالأولوية لما قمت بكتابته ، سأقوم بعمل التالي :

سأقول له عندما تقوم بعمل Object  جديد ضع الشركة مثلا Nissan  و سأقوم بالرجوع إلى الأسطر في الأسفل و اجعلها جمل ملاحظات .

أنا فعلياً قمت بتعريف الـ Object ، و لكن لم أقم بإسناد أي قيمة ، فقط قم بطباعة الـ Make  و عندما أقوم بتنفيذ التطبيق سيقوم بطباعة كلمة Nissan  ؛ من أين أتت هذه الكلمة !!!!

هذه الكلمة أتت من الـ Constructer    و هو كما قلت يتم استدعاؤه ضمنياً عندما تقوم بعملية استنساخ Object  جديد ،

هنا أيضاً مفهوم آخر ذكرناه في الMethods و سنعيده مرة أخرى  ، ألا و هو الـ Overload ، و هو إمكانية كتابة نفس الـ Method بنفس الاسم ، لكن مع اختلاف عدد الـ Parameter الموجود بداخلها ، لاحظوا أننا تكلمنا أنه داخل الـ Method بإمكانك إضافة  Parameter معينة  يتم اسنادها من خارج الدالة و يتم التعامل معها من داخل الدالة .

سنقوم بإضافة دالة جديدة و هي عبارة عن public Car و لكن سنقوم بإضافة Parameter  من خارج الدالة ، و تسمى هذه العملية Overload ، فسأقول له مثلاً string make  و string model  و int year و string color  ، و لاحظوا أن الكلمة make  تختلف تماما عن الكلمة Make لأننا تكلمنا أن لغة سي شارب هي لغة Case sensitive  فالحرف الصغير يختلف عن الكبير ، إذا في الـ overload هذه هنا سأقوم بعمل التالي ، حيث أنني في السطر رقم 13 ثمت بتعريف Object  جديد و القوسين فارغين ، فعليا قام باستدعاء الدالة التي قمنا بكتابتها ، و لكن أريد منه أن يقوم في عملية الـ Initialization أن أسند إليه قيماً و يقوم مباشرة بوضعها داخل كيان الـ Object  للتعامل معها لاحقاً .

فمثلاً سأقول له كالتالي :

الـ Make ذات الحرف الكبير اجعلها الـ make ذات الحرف الصغير ،  و التي أرسلتها من خارج الدالة

و كذلك بالنسبة للـ Model & Year & Color ، نعود للأعلى في السطر 13 ، بمجرد فتح القوس الأول يقوم بإظهار خيارات ، و بالضغط على الأسهم الظاهرة ، ستلاحظ أنه يوجد أكثر من Method يمكن استدعاؤها ، و هنا الأولى لا تحتاج أي Parameter و التي استخدمناها في السطر السابق ، و لكن هنا أريد استخدام الثانية ، حيث أريد اسناد الشركة و الموديل و السنة و اللون في نفس السطر ، فسأقول له  BMW مثلا , و كذلك الموديل و السنة و اللون ، إذا قمت بإنشاء Object جديد و قمت باستدعاء دالة البناء التي تحتوي على Parameter .

إذا عندما أقوم بعمل طباعة لنوع الشركة ، لن يقوم بإعادة اسناد Nissan بل سيقوم بطباعة BMW لأني قمت بإسنادها في بداية انشاء التطبيق  .

فهذا هو مفهوم الـ Constructer ، و هو مميز جداً   ، و استخدامه مفيد جداً في حالات كثيرة .

 

كلمة Static :

القسم الرابع من درسنا هو كلمة Static  ، لاحظوا أننا من أول تطبيق و حتى الآن ، كانت ترافقنا كلمة static الموجودة في الـ voidMain ، فقد تكلمنا عن int و string و void و تحدثنا عن الـ Class و كيف يمكننا استخدامه  و تحدثنا عن كلمةnew و تعلمنا كيف يمكن استخدامها  .

لطن ما معنى كلمة static ، و لماذا ترافقنا دائماً ، و لماذا في درس الدوال عندما قمنا بإضافة دالة ، وضعناها أيضاً من النوع Static كي نتمكن من استخدامها داخل الـ  voidMain ؟

الحقيقة أن كلمة static هي شيء يكون standard في كل الكلاس ، فكلمة Make و Model و Year و Color هي لا تتبع للكلاس ،هذه تتبع للـ Object المستنسخ من الكلاس ، فإن قمت بكتابة Car و بعدها نقطة ، فلن أجد الـ property السابقة ، لماذا ؟؟

لأن الـ Property الموجودة هنا تكون تابعة للـ Object الذي يأتي بعد عملية الاستنساخ ، فهنا عندما قمت باستنساخ Object جديد و وضعت myCar و النقطة ، حصلت على كل الـ Property الموجودة فيه ، و لدي أيضاً دوال ستكون متاحة هنا ، لماذا؟

لأنها ليست من النوع static

أما عندما أقوم بتعريف متغير جديد من النوع static ، لاحظوا أنني قمت بتعريف Property جديدة و لكنها من النوع static ، فهي تعني أن هذه الـ Property يمكن استدعاؤها من الكلاس نفسه ، بذكر اسم الكلاس قم ارفاقه مباشرة و ارفاق اسم الـ static ، إذاً عندما أكتب Car و هي اسم الكلاس بالحرف الكبير ، و اضع النقطة ، مباشرة أصبح لدي Property يمكن استخدامها على مستوى الـ Class .

 

دعونا الآن نتعامل مع الكلمة static بشكل أكبر .

لاحظوا هنا في داخل الكلاس ، وضعت أنه عند تعريف متغير جديد سيقوم بتغيير الـ Make ، مبدئياً سأقوم بعملها جملة ملاحظة ، و سأضع ، عندما يتم انشاء Object جديد ، قم بزيادة الـ Count برقم 1 ، فإذا قمت بطباعة Car.Count ، فعملية الزيادة لا تتم في الـ Constructer الذي يقوم بإعطاء parameter ، فأنا عندما قمت بإنشاء مجسم جديد ، لم أقم باستخدام هذا الـ Constructer ، بل قمت باستخدام الثاني ، و الذي يقوم بإعطاء وParameter ، ففعلياً هنا لا يوجد زيادة ، فبالتالي تظهر القيمة 0 ، لذلك سنقوم بعمل جملة الزيادة جملة ملاحظة و وضعها في الـ  Constructer الثاني ، و نجعل السيارة الثانية فارغة تستدعي الـ Constructer الأول ، و بذلك تكون السيارة الأولى و الثالثة تستدعي الـ Constructer الثاني ، أما الثالثة ، فتقوم باستدعاء الأول ، و عندها في كل Constructer يتم زيادة القيمة بواحد ، و لدي 3 سيارات ، فعندما أقوم بطباعة الـ Count يجب أن يظهر الرقم 3 .

 

موضوع الـ static  ليس حصرياً على الـ Property بل يمكن استخدامه كذلك في الـ Method .

لاحظواً أننا طول الوقت ، و من أول سطر لم نقم باستنساخ مجسم من الـ Console Class ، لم نقل له أعطني مجسم جديد و اريد استخدام هذه الدالة .

لاحظوا أن الـ Method ذات الاسم WriteLine تابعة مباشرة لاسم الكلاس ، و ليست تابعة لـ Object يتم اشتقاقه من الكلاس .

ايضاً مر معنا في درس التاريخ و الوقت أننا قمنا بالتعامل مع هذه الـ Property المسماة Now ، و هي لا تحتاج لعملي اشتقاق من الـ Data Type المسماة DateTime ، فقد حصلت عليها مباشرة من خلال النقطة ، لأن هذه الProperty عبارة عن static .

أيضاً لو لاحظتم في درس المصفوفات ، حيث تعاملنا مع دالة Reverse ، و هي ايضاً لا تحتاج لعملية اشتقاق من الكلاس Array .

إذا بالمثل سأقوم بإنشاء Method جديدة ، هذه الدالة من النوع static  أي أنها تابعة للكلاس بشكل كامل ، و سأقوم باستدعائها بالكلاس الرئيسي ، و حيث أن هذه الدالة تقوم بطباعة Count
و لو قمت بتنفيذ التطبيق سيقوم بطباعة عدد السيارات التي قمت بإنشائها من هذا الكلاس .

 

مصطلحات الدرس :

Garbage Collector :

Static :

Constructer :

Object Oriented Programming (OOP) :

Property   :

Object :

Class :

Dot Net Runtime :

Common Language Runtime (CLR) :

namespace   :

Nested Class :

null   :

managed   :

unmanaged  :

initialize   :

Initialization :

Parameter :

Reverse :

Count :

Public  :

الأسطر البرمجية التي قمنا بتنفيذها في هذا الدرس

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ObjectLifeTime
{
    class Program
    {
        static void Main(string[] args)
        {
            //Car myCar = new Car();
            Car myCar = new Car("BMW","Z",1990,"Yellow");
            Car myCar2 = new Car();
            Car myCar3 = new Car("BMW","Z",1990,"Yellow");
            
            Car.PrintCount();
            //myCar.Color = "Black";

            //Car myOtherCar;
            //myOtherCar = myCar;
            //myOtherCar.Color = "Red";
            //myOtherCar = null;
            //myCar = null;
            
            //Console.WriteLine("{0}", Car.Count);
            Console.ReadLine();
            
        }
    }
    class Car
    {
        public Car()
        {
            //Make = "Nissan";
            Count++;
        }
        public Car(string make,string model,int year,string color)
        {
            Make = make;
            Model = model;
            Year = year;
            Color = color;
            Count++;
        }

        public static void PrintCount()
        {
            Console.WriteLine("{0}", Count);
        }

        public static int Count { get; set; }
        public string Make { get; set; }
        public string Model { get; set; }
        public int Year { get; set; }
        public string Color { get; set; }
    }
}