Advertisement
  1. Game Development
  2. Unity 3D
Gamedevelopment

كيفية بناء نظام وقت الترجيعترجيع الوقت مثل Prince-of-Persia، الجزء 2

by
Length:MediumLanguages:
This post is part of a series called How to Build a Prince-Of-Persia-Style Time-Rewind System.
How to Build a Prince-of-Persia-Style Time-Rewind System, Part 1

Arabic (العربية/عربي) translation by Ayman Amar (you can also view the original English article)

Final product image
What You'll Be Creating

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

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

مستعد؟ لنذهب!

تسجيل بيانات أقل واقحام

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

لكن ما يمكننا القيام به بدل من ذلك هو التسجيل فقط 4 مرات في الثانية والاقحام بين هؤلاء الإطارات الرئيسة. بهذه الطريقة نحفظ 92% حجم المعالجة، والحصول على النتائج لايمكن تمييزها من تسجيلات 50-إطار، كما أنها تلعب في غضون أجزاء من الثانية.

سوف نبدأ بتسجيل فقط إطار مفتاحي كل x من الإطارات. للقيام بذلك، نحن بحاجة أولاً إلى هذه المتغيرات الجديدة:

المتغير keyframe هو الإطار في method FixedUpdate التي سوف يقوم بتسجيل بيانات اللاعب. حاليا، تم تعيينها لـ 5، مما يعني أنه كل مرة خامسة method FixedUpdate تدور خلالها، البيانات سوف تسجل كما FixedUpdate تعمل 50 مرة في الثانية، هذا يعني سوف تسجل 10 إطارات في الثانية، مقارنة بـ 50 من قبل. سيتم استخدام المتغير frameCounter لعد الإطارات حتى الإطار المفتاحي التالي.

الآن قم بتكييف مجموعة التسجيل في دالة FixedUpdate لتبدو مثل هذا:

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

أولاً، نحن بحاجة إلى متغير frameCounter اخر للاحتفاظ بتعقب ليس لتسجيل البيانات، لكن لبدئه مرة أخرى.

قم بضبط الكود الذي قوم باستعادة موقع اللاعب للاستفادة منه بنفس الطريقة التي نسجل بها البيانات. دالة FixedUpdate ينبقي بعد ذلك أن تظهر هكذا:

عندما تقوم بترجيع الوقت الان، اللاعب سوق يقفز بالخلف إلى أماكنه السابقة، في نفس الوقت!

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

هؤلاء سوف يحفظون بيانات اللاعب وواحد من الإطار المفتاحي مسجل قبل ذلك حيث يمكننا أن الاقحام بين هاتين.

بعد ذلك نحن بحاجة إلى هذه الدالة:

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

جزء استعادة البيانات الخاص بنا ينبغي أن يبدو مثل هذا:

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

من أجل جعل هذا يعمل، تحتاج أيضا إلى المتغير firstRun:

ولإعادة التعيين عندما يتم رفع الضغط عن زر space:

هنا كيف يعمل الإقحام:

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

كل هذا يحصل من خلال دالة الـ Lerp، حيث أضفنا الموقع الحالي (أو الدوران) والسابق. بعد ذلك يحسب كسر الإقحام، التي يمكن أن يصل من 0 إلى 1. بعد ذلك يتم وضع اللاعب في الموقع المساوي بين هاتين النقطتين المحفوظتين، على سبيل المثال، 40% على الطريقة إلى الإطار المفتاحي الأخير.

عندما تقوم بتبطيئها وتشعيلها إطار بإطار، يمكنك فعليا رؤية شخصية اللاعب تتحرك بين هاتين الإطارين المفتاحيين، لكن خلال اللعب، إنها غير ملاحظة.

وهكذا لدينا إلى حد كبير تخفيض تعقيد إعداد ترجيع الوقت وجعله أكثر استقرارا.

فقط تسجيل عدد محدد من الإطارات المفتاحية

الآن قد قلصنا إلى حد كبير عدد الإطارات إننا فعلا من بأمان، يمكننا أن نتأكد أننا لا نقم بحفظ الكثير من البيانات.

الآن للتو قمنا بتكويم البيانات المسجلة داخل المصفوفة، التي لن تفعل على المدى الطويل. كما تنمو المصفوفة، سوف تصبح غير عملية أكثر، سوف يستغرق الوصول كميات كبيرة من الوقت، 

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

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

استخدام كلاس مخصص للاحتفاظ ببيانات لاعب

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

ما يمكن أن نفعله، على أية حال. هو إنشاء كلاس منفصل لإجراء كل هذه الأشياء، وربما أكثر من ذلك (إذا كان هذا ضروري في المشروع الخاص بك).

التعليمات البرمجية لكلاس مخصص للعمل كحاوية للبيانات تبدو مثل هذا:

يمكنك إضافته إلى ملف TimeController.cs، قبل بدء إعلان الكلاس مباشرة. ما يفعله هو توفير حاوية لحفظ كل من موقع ودوران اللاعب على حد سواء. يسمح method المنشئ بالإنشاء مباشرة مع المعلومات الضرورية.

باقي الخوارزمية سوف تحتاج إلى التكيف للعمل مع النظام الجديد. في method Start، يجب تهيئة المصفوفة:

وبدلاً من قول:

يمكننا حفظه مباشرة داخل كائن الإطار المفتاحي:

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

إضافة تأثير التشويه لتحديد إذا كان الترجيع يحدث

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

دعونا نفعل شيئا مماثل إلى كيف يفعل Prince of Persia، وإضافة بعض الضبابية.

A screenshot of the time-rewinding from Prince of Persia The Forgotten Sands
ترجيع الوقت من Prince of Persia: The Forgotten Sands

Unity يسمح لك بإضافة مؤثرات كاميرا متعددة في أعلى بعضهم البعض، ومع بعض التجريب يمكنك صنع واحد الذي يناسب مشروعك تماما.

قبل أن يمكننا استخدام التأثيرات الأساسية، نحن بحاجة إلى استيرادها. للقيام بهذا، انتقل إلى Assets > Import Package > Effects، واستيراد كل ما يتاح لك.

View of the effects-menu in Unity 3D

يمكن إضافة التأثيرات المرئية مباشرة إلى الكاميرا الرئيسية. انتقل إلى Components > Image Effects وأضف تأثير Blur وBloom. الجمع بين هذين ينبغي أن يوفر تأثير جميل للذي سوف نقوم به لأجله.

View of the effects-inspector in Unity 3D
هذه هي الإعدادات الأساسية. يمكنك ضبطهم لأفضل تناسب مع المشروع الخاص بك.

عندما تجربها الآن، اللعبة ستعمل هذا التأثير في كل الوقت.

A screenshot of the effect in use

الان نحن في حاجة إلى تفعيله وإلغاء تفعيله على التوالي. لأجل هذا، الـ TimeController يحتاج إلى استيراد صور التأثيرات. أضف هذا السطر إلى البداية القصوى:

للوصول إلى الكاميرا من TimeController، أضف هذا المتغير:

وأنسبه في دالة Start:

بعد ذلك أضف هذه التعليمة البرمجية لتفعيل التأثيرات خلال وقت الترجيع، وجعلهم غير مفعلين خلاف ذلك:

عند الضغط على زر space، يمكنك الآن ليس فقط ترجيع المشهد، ولكن يمكنك أيضا تنشيط تأثير الترجيع على الكاميرا، والقول لللاعب أن شيئا ما يحدث.

التعليمة البرمجية TimeController بأكملها يجب أن تبدو هكذا:

قم بتنزيل حزمة البناء المرفقة وجربها!

خاتمة

لعبة ترجيع الوقت الخاصة بنا الآن أفضل بكثير من قبل. الخوارزمية في تحسن ملحوظ وتستخدم 90% أقل من قوة المعالجة، وأكثر استقرارا، ولدينا دليل جميل يقول لنا أننا حاليا قيد ترجيع الوقت.

الآن اذهب وانشئ لعبة باستخدام هذا!

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.