من Blueprint أو من C++
كل عقدة من عقد اختبار اللعب في هذه الصفحة موجودة في فئة Protokite | Playtest في قائمة إجراءات Blueprint، ولا تحتاج إلى أكثر من تفعيل الإضافة. وكل عقدة تستدلّ على اختبار اللعب من الرسم الذي استدعاها. وتستدعي C++ الدوالّ نفسها علىUProtokitePlaytestLibrary، وتمرّر أي كائن في عالم اللعبة (الممثّل أو
الواجهة التي تُجري الاستدعاء، أي this) حيث تستدلّ العقدة على الاختبار بنفسها. أضف وحدة الإضافة إلى
ملف Build.cs الخاص بوحدة لعبتك، وضمّن ترويستها:
ما الذي سمح به اللاعب
يسأل البناء لاعبه عمّا يجوز لاختبار اللعب أن يجمعه قبل أن يجمع شيئًا، وإجابته هي التي تقرّر ما تفعله بقية هذه الصفحة:
وتجيب Protokite Is Playtest Feature Enabled عن الأمرين معًا أصلًا: فميزة يشغّلها الاختبار ويستثنيها
اللاعب تُقرأ مُطفأة في كل موضع. وتعطي Protokite Get Playtest Consent الإجابة نفسها، أما السؤال وكيف
تطرحه لعبتك بشاشاتها والإعداد الذي يوقفه ففي صفحة
إضافة Unreal.
ولا يدخل نموذج الملاحظات في تلك الإجابة. فهو لا يُرسل إلا حين يملؤه اللاعب ويضغط «إرسال»، وذلك
فعله هو في الحالين — ونموذجٌ تعذّر على تشغيل سابق إرساله يُرسل لاحقًا مهما كانت إجابته بعد ذلك.
تسجيل الفيديو
تُسجَّل شاشة اللعبة منذ اللحظة التي يُحمّل فيها الاختبار، بتسجيل واحد لكل تشغيل، في ملف WebM يشغّله المتصفّح. ولا يُسجَّل الوقت الذي تكون فيه اللعبة في الخلفية. وتضبط إعدادات Video Recording في Protokite Playtest Settings المقاس ومعدّل الإطارات ومعدّل البتّ — 1280×720 و30 إطارًا في الثانية وVideo Bitrate (kbps) بقيمة 2000 افتراضيًا — وحدّين أيهما جاء أولًا: Recording Length Limit (Minutes) بقيمة 60، وRecording Size Limit (MB) بقيمة 1536. ويُرفع التسجيل إلى جلسته:- حين ينهيه حدّ الطول أو حدّ الحجم؛
- حين تطلب اللعبة ذلك، عبر Protokite Stop And Upload Playtest Recording أو زر Upload your recording في نموذج الملاحظات؛
- حين توقفه اللعبة نهائيًا، عبر Protokite Stop Video Recording؛
- وفي بداية تشغيل لاحق، لكل ما لم يستطع تشغيل سابق إرساله: رفع فاشل، أو خروج، أو انهيار.
الخروج من اللعبة لا يرفع. فلا يمكن إرسال تسجيل كامل أثناء الإغلاق، ولذلك يُحفظ ويرسله التشغيل
التالي. ويُحذف التسجيل بعد رفعه، كما يحذف التشغيل التالي تسجيلًا لم تبدأ له جلسة اختبار قط، إذ لا
سبيل إلى إرساله أبدًا.
Saved/ProtokitePlaytest/Recordings/، ضمن Recordings Disk Budget (MB) بقيمة 4096. وحين تضيق المساحة تُحذف أقدم مقاطع الاختبار أولًا، وتُحذف التسجيلات المنتظرة للرفع أخيرًا.
ولا تعرض على اللاعب طريقةً لإرسال تسجيله إلا ما دامت Protokite Can Send Playtest Recording صحيحة. فهي
كاذبة حين لا تكون جلسة قد بدأت للتسجيل، والضغط على زر حينها سيوقف التسجيل ولن يرسل شيئًا.
إخبار اللاعب بأن تسجيله أُرسل
اربط On Recording Upload Finished لتخبر اللاعب بما جرى. يُطلق مرة واحدة حين ينتهي تسجيل التشغيل، ومعه قيمتان:- Uploaded صحيحة حين يصل التسجيل إلى جلسته.
- Why Not تقول لماذا لم يُرفع، بما في ذلك تعذّر بدء الرفع من أصله (لا جلسة Protokite يُرسل إليها، أو حزمة Flock لا تعمل). والتسجيل الذي لم يُرفع يُحفظ لتشغيل لاحق، ما لم تكن جلسة لم تبدأ له قط.

عند BeginPlay، اربط On Recording Upload Finished واطبع Why Not حين تكون Uploaded كاذبة.
UFUNCTION()، لأن الحدث مندوب ديناميكي (dynamic delegate) (الوحدة والترويسة في
من Blueprint أو من C++):
التحليلات الثقيلة
ترسل الإضافة ما يلي عبر تحليلات حزمة Flock، ضمن فئةplaytest، وتُقرأ في Dashboards → Game
Metrics:
-
performance_windowلكل عشر ثوانٍ من اللعب: وسيط زمن الإطار والنسبتان المئويتان 95 و99 منه، والتلعثمات، والذاكرة المستخدَمة وذروتها؛ -
level_loadedلكل مرحلة يحمّلها نسخة اللعبة هذه، ومعها المرحلة السابقة، ومدة التحميل إن كان تحميلًا حاجزًا؛ - وأحداثك أنت، عبر Protokite Record Playtest Event.
تسجيل حدث من أحداثك
تأخذ Protokite Record Playtest Event اسم حدث وخصائصه. ابدأ الخصائص بـMake Flock Event Properties (لا تحتاج إلى أي توصيل)، ثم أضف عقدة Flock Event Property لكل خاصية (Integer أو String أو Float أو Boolean أو String Array)، كلٌّ منها تغذّي التالية، ووصّل الأخيرة بـProperties:
حين يسقط الزعيم، سجّل boss_defeated ومعه عدد الثواني التي استغرقها القتال.
- لا يكون اختبار لعب قائمًا، أو يُبقي التحليلات الثقيلة مُطفأة (أو استثنى اللاعب بيانات اللعب)؛
- يكون الاسم مما ترسله الإضافة بنفسها،
performance_windowأوlevel_loaded؛ - ترفض حزمة Flock الحدث: تحليلاتها مُطفأة، أو الموافقة محجوبة، أو الاسم فارغ، أو أطول من 200 حرف.
الاستثناءات
تبقى الاستثناءات من شأن حزمة Flock. فهي تلتقط أسطر الأخطاء، وفشل التحققات، وأخطاء Blueprint مثل Accessed None، والانهيارات، بإعداداتها هي تحت Analytics | Exceptions، وتبلّغ عنها في Diagnostics → Errors. ولا يشغّل مفتاح الاستثناءات في اختبار اللعب ذلك ولا يطفئه؛ وحين يطلب الاختبار الاستثناءات ويكون Analytics Capture Exceptions مُطفأً، يحذّر السجل مرة واحدة عند بدء الجلسة. وللتحقّق من وصول الاستثناءات إلى لوحة التحكم، اكتبFlock.RaiseTestException error أو
Flock.RaiseTestException blueprint 100 في طرفية بناء Development. فمئة حالة من العطل نفسه تصل بلاغًا
واحدًا، ثم بلاغ تكرار واحدًا يعدّ التسعة والتسعين الباقية بعد أن تُغلق نافذة التكرار.
نموذج الملاحظات
تُكتب أسئلة النموذج في صفحة Feedback form الخاصة بالاختبار في Protokite. وحين ينشر الاختبار نموذجًا، يفتحه اللاعبون بمفتاح Feedback Form Key (F9 افتراضيًا؛ واضبطه على none لتعطيل المفتاح)، أو تفتحه لعبتك عبر Protokite Open Feedback Form — من قائمة الإيقاف المؤقت مثلًا. وتحقّق من Protokite Can Open Feedback Form أولًا: فهي كاذبة حين لا ينشر الاختبار نموذجًا، فتستطيع لعبتك إخفاء مدخلها الخاص بدل أن تعرض ما لا وجود له. وفي قائمة إيقاف مؤقت مبنية على هيئة Widget Blueprint، ضع هذه العقد على حدث On Clicked لزر «أرسل ملاحظاتك» فيها؛ فالحدث المخصّص في الصورة يقوم مقام ذلك الحدث.
مدخل «أرسل ملاحظاتك» في قائمة الإيقاف المؤقت: لا تفتح النموذج إلا حين يوجد.

نموذج منشور، مبني من اختبار اللعب: كل أسئلته، والزر الذي يرسل التسجيل.
لاستيراد صورة للنموذج:
- استوردها على هيئة texture، مثلًا بسحبها إلى Content Browser. وتناسب لوحة النموذج الداكنة الصورُ ذات الخلفية الشفافة.
- افتح الـ texture واضبط Padding and Resizing على None. وإلا مُدّت إلى قوة للعدد 2 فظهرت باهتة، أو حُشيت فظهرت مضغوطة فوق شريط من الحشو.
- أبقِ خرائط mip فيها، لتبقى ناعمة حين تُرسم أصغر: Mip Gen Settings على أي قيمة غير NoMipmaps، وغير FromTextureGroup إن كانت Texture Group هي UI.
- احفظها، واخترها في Feedback Form Logos أو Feedback Form Footer Logo.
نموذج من عندك
لترسم الأسئلة في واجهتك أنت بدل النموذج المدمج، اقرأ النموذج، وسجّل إجابات اللاعب، وافحصها، ثم أرسلها:- اقرأ النموذج. تعيد Protokite Get Feedback Form القيمة false، مع نموذج فارغ، حين لا ينشر الاختبار نموذجًا. ويحمل Form العنوان والوصف وFields، حقلًا لكل سؤال. ولكل حقل Id، وType (نوعه)، وLabel، وHelp Text، وOptions (لسؤال الاختيار)، وRequired.
- اختر عنصر التحكّم بحسب نوع السؤال. فكّك الحقل، وقارن Type فيه بـ Equal Exactly (String) مع عقدة Protokite Feedback Question Kind لكل نوع (Text وText Area وRating وSelect وCheckbox) بدل كتابة النوع بيدك: فالأنواع تتطابق حرفًا بحرف. وعامِل نوعًا لا تعرفه معاملة النص، فهكذا يقرؤه الخادم.
-
سجّل كل إجابة تحت Id سؤالها بالعقدة الخاصة بنوعه. واترك Answers في العقدة الأولى دون توصيل، كما في
الصورة: فهي تبدأ من غير إجابات.
هذه العقد الأربع لا منافذ تنفيذ لها: تعيد كل منها قيمة Answers جديدة مضافًا إليها تلك الإجابة، وتترك Answers التي أُعطيت لها دون تغيير. فمرّر مخرج Answers من كل عقدة إلى مدخل Answers في التي تليها، واحفظ المخرج الأخير في متغيّر (من نوع Protokite Playtest Form Answers). والإجابة التي لا يُحفظ مخرجها تضيع.
- افحص الإجابات بـFind Feedback Form Problems (Answers وForm). فهي تسرد كل سؤال سيرفض الخادم الإجابات بسببه، ولكلٍّ منه Field Id وMessage تعرضها للاعب بجوار ذلك السؤال. والقائمة الفارغة تعني أنها ستُقبل.
- أرسلها بـProtokite Send Feedback Form Answers. وتعيد false، مع تحذير في السجل، حين لا يكون للاختبار نموذج أو لا يكون هناك من تُرسل الإجابات باسمه. والإجابات التي يتعذّر إرسالها الآن تُحفظ على القرص ويرسلها تشغيل لاحق.
LogProtokitePlaytest، Sending the feedback form.، وحين يقبلها Protokite The feedback form was sent. (أو
The feedback form is kept until the Flock SDK is running. حين لا تكون حزمة Flock قد بدأت). أما الرفض فيسجّل
The feedback form was not sent مع سبب Protokite، والسؤال الذي رفضه حين يسمّيه، وطريقة الإصلاح.
في الصورة، fun وcomments هما Id سؤالين في نموذج الاختبار: سؤال تقييم وسؤال نصي. استخدم Id كل سؤال في
نموذجك أنت.

قيّم المتعة بـ4، وأضف تعليقًا، واحفظ النتيجة في Answers، ولا ترسلها إلا حين لا ينقصها شيء.
FProtokitePlaytestFormAnswers واحدة في مكانها، ويُفحص نوع الحقل بـIsOfKind وأسماء
ProtokitePlaytestFormFieldTypes:
fun وcomments وwould_play_again وplatform تمثّل أسئلة نموذجك أنت: استخدم المعرّفات (Id)
التي يسلّمك إياها النموذج.
عقد Blueprint
جميعها تحت Protokite | Playtest. وكل عقدة تستدلّ على اختبار اللعب من الرسم الذي استدعاها. وكل الأسماء تبدأ بـ”Protokite” عدا عقد الإجابات: Set Feedback … Answer وSet Feedback Chosen Option وFind Feedback Form Problems.تجريبه في المحرّر
قبل وجود أي اختبار لعب، أشّر على Record Video In Play In Editor في Project Settings → Plugins → Protokite Playtest Local Settings واضغط Play، أو اكتبProtokitePlaytest.RecordTestVideo 30 في طرفية بناء
Development. وتُحفظ مقاطع الاختبار تحت Saved/ProtokitePlaytest/Recordings/TestVideos/ ولا تُرفع أبدًا.
وأمام اختبار لعب حقيقي، اضغط Play بالإعدادات المذكورة في صفحة الإعداد وسجّل الدخول بـ
Flock.LoginWithDevice. ثم، في طرفية بناء Development:
وأوقات الانتظار موجودة لأن كل أمر في
-ExecCmds يُنفَّذ في الإطار الأول، قبل أن يكون قد سُجِّل شيء أو
بدأت جلسة.
فحص بناء اختبار اللعب
يفحصProtokitePlaytest.SelfTest كل ما يفعله بناء اختبار اللعب أمام Protokite الحقيقي دفعةً واحدة، ويسجّل
سطرًا لكل خطوة وعدًّا في النهاية: Playtest self-test finished: 16 passed, 0 failed, 1 skipped.
وأبنية Development فقط.
ويقف كل فحص إلى جوار طلب يجب أن يرفضه Protokite: مفتاح واجهة خاطئ، ومفتاح مفقود، وإصدار لا اختبار لعب
مرتبط به، وبدء جلسة لا يسمّي لاعبًا، ونموذج تنقصه إجابة مطلوبة أو يختار خيارًا ليس في القائمة، ونموذج
ورابط رفع ونهاية جلسة لجلسة غير موجودة. فالفحص الذي ينجح دائمًا لا يميّز بناءً سليمًا من بناء معطوب،
ولذلك لا يمرّ الرفض إلا بحالة HTTP الخاصة به، ومع النموذج بالسؤال الذي يسمّيه.
وهو لا يسجّل دخول أحد، فسجّل الدخول أولًا. ومن سكربت:
- ينهي جلسة التشغيل بوصفها خطوته الأخيرة، فشغّله في تشغيل مستقل. وأي جلسة كان ينبغي لرفضٍ أن يمنعها تُنهى فورًا، فلا يترك الفحص شيئًا مفتوحًا.
- يترك أثرًا في لوحاتك: نموذجًا مملوءًا على جلسته، وحدث
playtest_self_testواحدًا، وعطل Blueprint واحدًا أُثير مرتين ليُعدّ تكراره، وتسجيل التشغيل. - وتُتخطّى خطوة، مع ذكر السبب، حين لا يكون أحد قد أجاب عمّا يجوز لاختبار اللعب جمعه (أجب أولًا بـ
ProtokitePlaytest.AnswerConsent video_and_play_data)؛ وحين لا يشغّل الاختبار ميزتها؛ وحين لا يكون في البناء مُرمِّز فيديو، وهو كل منصة عدا Windows بنواة 64 بت؛ وحين لا يستطيع التشغيل الرسم (-nullrhi)، إذ لا يُسجَّل شيء؛ وحين يكون Analytics Cache Failed Events مُطفأً، إذ لا يمكن مراقبة بلاغ يُرسل لحظة إنشائه؛ ولاختبار مغلق ما لم تسمِّ واحدًا.