استخدام Unity3D في تطبيق iOS / Android الأصلي لنمذجة إضاءة المساحات المفتوحة

الصورة

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

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

تم تنفيذ العمل على مراحل على أساس المواصفات المطورة للمتطلبات والاستشارات من شركة BOOS LIGHTING GROUP حول موضوع المشروع.

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

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

    الصورة
  • يمكن أن تكون الطرق أقسامًا خطية وعناصر قوس ومساحة وخاتم. لكل عنصر ، الأبعاد ، الموضع ، نوع التخطيط ، الطبقة يمكن تخصيصها.

    الصورة
  • العناصر الزخرفية - السيارات والأشجار والشجيرات وعلامات الطرق

يمكن تدوير جميع عناصر المشهد وتحريكها. الإجراءات القياسية للعودة أو إعادة المحاولة مدعومة أيضًا. تسمح لك الإعدادات العامة للمشروع بتحديد نسيج dorg ، سطح الأرض ، عرض المعلمات الإضافية. يتم عرض المشهد في أوضاع 2D / 3D. وعند حساب الإضاءة على السطح ، يتم عرض خريطة لإضاءة السطح بألوان وهمية.

الصورة


إذا كان ذلك ممكنًا ، يجب أن يتم تنفيذ واجهة المستخدم بالكامل باستخدام أدوات iOS / Android أصلية.
المتطلبات الفنية الرئيسية للتطبيق هي أن تكون قادرًا على حساب إضاءة المسرح وفقًا للمواصفات الفنية للتجهيزات. كما كان مطلوبًا أيضًا قدرة كل تركيبات على عرض وعرض نمط الإشعاع الخاص بها (منحنيات شدة الضوء) في أوضاع 3D / 2D.

اختيار المنصة


لتنفيذ المشروع ، اخترنا Unity لتكون أكثر ملاءمة لنا لتنفيذ الوظائف المطلوبة. بشكل عام ، كانت شركتنا لديها خبرة في العمل مع محركات ومنصات ثلاثية الأبعاد أخرى (OpenSceneGraph و Ogre3D و LibGdx) ومن الناحية الفنية يمكنهم جميعًا التعامل مع المهمة المطلوبة ، ولكن هذه المرة وقع الاختيار على Unity ، مما يجعل من السهل إدارة المشهد أثناء التطوير والتصحيح في عملية العمل.

الصعوبات الرئيسية


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

العمل مع واجهة المستخدم الأصلية


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

الصورة


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

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

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

حساب الإضاءة


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

مثال على ملف IES بسيط
IESNA91[TEST] Simple demo intensity distribution [MANUFAC] Lightscape Technologies, Inc. TILT=NONE 1 -1 1 8 1 1 2 0.0 0.0 0.0 1.0 1.0 0.0 0.0 5.0 10.0 20.0 30.0 45.0 65.0 90.0 0.0 1000.0 1100.0 1300.0 1150.0 930.0 650.0 350.0 0.0 


لعرض نمط الإشعاع ، تم استخدام نوعين من العرض:

  • منحنيات شدة الضوء (KSS) هي رسم بياني ثنائي الأبعاد يوضح شدة الضوء في إحدى الطائرات الرئيسية اعتمادًا على الاتجاه. من أجل الراحة ، يمكن تمثيل هذا الرسم البياني في كل من نظام الإحداثيات القطبية والديكارتي.

    الصورة
  • الجسم الضوئي - صورة ثلاثية الأبعاد لشدة الضوء في اتجاهات مختلفة

    الصورة

وحدة الحساب


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

  • على منصة iOS ، يمكن لـ Unitu استدعاء وظائف C مباشرة ، لذا فقط قم بنسخ شفرة المصدر للوحدة مباشرة في المشروع وإضافة فئات لتفاعلها مع Unity. يمكن تخزين الفصول مباشرة في مشروع iOS ، وفي مجلد الإضافات ، والتي يتم نسخها تلقائيًا عند تصدير المشروع إلى Xcode. مثال على استدعاء دالات C ++ كما يلي:

     [DllImport("__Internal")] public static extern void calculateLight([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] Light[] lights, int size, ref CalculationResult result); 
  • على نظام Android الأساسي ، يجب ترجمة وحدة C ++ مسبقًا إلى مكتبة منفصلة. يمكن القيام بذلك مباشرة عن طريق إضافة مصادر C ++ إلى المشروع وإعداد التقدير لبناءها في المكتبات.
  • أيضًا ، لتصحيح الأخطاء واختبار جزء الوحدة ، تم إجراء التطوير على جهاز Windows ، لذلك كان من الضروري توصيل شفرة المصدر للوحدة النمطية في Windows أيضًا. يتم ذلك بشكل مشابه لمشروع android ، فقط في هذه الحالة يتم تجميع الملفات التي تم تنزيلها في مكتبة dll وتوصيلها بالمشروع.

عرض الخريطة الخفيفة


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

الصورة


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

تم تحليل خريطة الإشعاع الناتجة للحصول على الحد الأدنى والقيمة القصوى التي تم من خلالها بناء نسيج متدرج أحادي البعد (GradientRamp). باستخدام هذا الملمس ، تم تحويل شدة الضوء إلى ألوان وهمية مباشرة في تظليل الشظايا. في الوقت نفسه ، تم استخدام نفس تظليل أسطح الطرق المختلفة وسطح الأرض ، وتم تبديل وضع الإضاءة باستخدام تظليل " تجميع متعدد ".

توليد ملف PDF


وفقًا للمتطلبات الفنية ، كان من المقرر إنشاء تقرير للمستخدم يحتوي على معلومات حول المشهد العام (الأبعاد والصور الخاصة به ومعلمات الإضاءة) ومعلومات حول كل نوع من وحدات الإنارة المستخدمة ، مع الإشارة إلى موقعها واتجاه الخصائص بالإضافة إلى الرسوم البيانية KCC وعرض الجسم الفوتومتري.
نظرًا لأنه سيتم عرض التقرير على كل من iOS و Android ، كان من الضروري إنشاء تقريره مباشرة في وحدة Unity ، ثم عرضه باستخدام الأدوات الأصلية القياسية.

الصورة

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

إذا كان الاختبار بتنسيق pdf على جهاز سطح المكتب ، فقد كان إنشاء ملف pdf في ترتيب عدة ثوانٍ ، ثم عند الاختبار على iPad mini 3 وصل هذه المرة بسهولة 1-3 دقائق. بطبيعة الحال ، يجب نقل إنشاء التقرير إلى سلسلة رسائل منفصلة ، لتجنب المشاكل مع تعليق الواجهة. في الحالة العامة ، هذه ليست مشكلة ، ولكن هذه ليست الحالة عند استخدام Unity ، حيث يُحظر صراحة استخدام Unity API من خارج سلسلة المحادثات الرئيسية. في الوقت نفسه ، بالنسبة للتقرير ، كنا بحاجة ، على الأقل ، إلى تقديم CSS وصورة المشهد ، والتي يجب أن تتم فقط من الدفق الرئيسي.

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

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

UniRx


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

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

لقد سهل استخدامه بشكل كبير التفاعل بين الخيوط ويظهر المثال أدناه أنه يمكنك تشغيل عدة طرق بتسلسل صارم ، ولكن في سلاسل مختلفة

مثال على الرمز
 var initializer = Observable.FromCoroutine(initMethod); var heavyMethod1 = Observable.Start(() => doHardWork()); var mainThread1 = Observable.FromCoroutine(renderImage); var heavyMethod2 = Observable.Start(() => doHardWork2()); initializer.SelectMany(heavyMethod1) .SelectMany(mainThread1) .SelectMany(heavyMethod2) .ObserveOnMainThread() .Subscribe((x) => done()) .AddTo(this); 

في هذا المثال ، سيتم تشغيل طريقة doHardWork () بالتسلسل في مؤشر ترابط الخلفية. بعد اكتماله ، سيتم تشغيل تجعل الأمر () في سلسلة الرسائل الرئيسية ، وبعد ذلك سيتم تنفيذ doHardWork2 () مرة أخرى في سلسلة المحادثات الخلفية.

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

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

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


All Articles