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

النسخة 2017.2 من محرك Unity متاحة الآن!

السلام عليكم ورحمة الله وبركاته

عن النسخة :

النسخة التي وُعدنا بها من شركة Unity لمحركها الشهير Unity Engine أصبحت متاحة الآن! نعم النسخة 2017.2 أصبحت قابلة للتحميل، وبإمكانك الحصول عليها من هنا. التي تحتوي على العديد من الميزات الجديدة والتحديثات وحلول لمشاكل كانت تؤرق المطورين.

العناوين الرئيسية :

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

  • محرر المراحل Tilemap : 

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

مدير الإنتاج cinemachine الثنائي الأبعاد:

شهدنا في الإصدارات السابقة تواجد مدير الإنتاح الغني عن التعريف cinemachine للألعاب ثلاثية البعد 3D والتي بإمكانك التحكم في الكاميرات الموجودة في لعبتك وعمل الكثير من الميزات الحصرية التي تختصر عليه المئات من الساعات لعملها بمفردك، في هذه النسخة أصبحت الميزة متاحة لألعاب البعد الثاني 2D أيضاً، كما هو موضح في الفيديو السابق.

الدروس التفاعلية Interactive Tutorials :

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

ميزة إستيرا المجسمات Asset Management :

أو ما يعرف بالـ DCC المختصر من Digital Content Creation ، فالآن أصبح من السهل التعامل مع التطبيقات المختلفة مثل Autodesk وغيرها، ليس فقط إضافة ميزات لما تحويه هذه الملفات مثل الملف الشهير FBX الذي يحوي المجسمات والصور والحركة فحسب، بل إمتد الموضوع لإضافة مجسم جديد يمكنك إنشاءه وربطه لاحقاً بملف من تلك البرامج مما يتيح لك التعديل الآني ومن غير معاناة من إنتظار الوقت الكثير لإنعكاس التعديلات بين البرامج، فلقد تم إضافة Linked Prefabs  إلى قائمة الإنشاء كما هو موضح في هذا الفيديو :

إضافات للواقع الإفتراضي/المعزز XR :

يتضح جلياً تركيز المحرك على إعطاء القدرة القصوى لمطوريه للتماشي مع أكثر التطبيقات طلباً في الوقت الحالي، فقد إعتبرت كبرى الشركات مثل Microsoft و Sony و Google سنة 2016 على أنها سنة الواقع الإفتراضي VR المختصر من Virtual Reality والواقع المعزز AR المختصر من Argumented Reality بجدارة، أو ما يعرف كليهما بالإختصار XR ، فهناك العديد من الميزات التي تم إضافتها لتسهل العمل مع هذه التطبيقات، فها هي تضيف Vuforia  إلى محركها ضمنياً، وتدعم OpenVR و Google ARCore كما في الفيديو التالي :

ليس هذا فحسب، فهناك بعض الإضافات والتحسينات كالتالي :

+ ميزة Timeline للأصوات : بإمكانك الآن التعامل مع الأصوات أيضاً
+ تحديثات بالـ Profiler لتحليل اللعبة بشكل أكثر تفصيلاً
+ ميزة Lightmap background لإضافة لايت ماب للأماكن الفارغ سابقاً
+ أصبحت الأشجار يتم حساب ال Lightmap الخاص بها أيضاً
+ تحسينات على نظام ال Particle System

 

الخلاصة

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