تحسين الأداء

*This content is translated using AI (Beta) and may contain errors. To view this page in English, click here.

تصف هذه الصفحة مشاكل الأداء الشائعة والممارسات الأفضل للتخفيف منها.

حساب السكربت

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

المشاكل الشائعة

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

  • الأحداث عالية التردد - ربط العمليات المكلفة بأحداث مستندة إلى الإطارات من RunService دون تحديد التكرار يعني أن هذه العمليات تتكرر في كل إطار، مما يؤدي غالبًا إلى زيادة غير ضرورية في وقت الحساب. تشمل هذه الأحداث:

التخفيف

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

مجالات MicroProfiler

النطاقالحساب المرتبط
RunService.PreRenderالكود المنفذ في حدث PreRender
RunService.PreSimulationالكود المنفذ في حدث Stepped
RunService.PostSimulationالكود المنفذ في حدث Heartbeat
RunService.Heartbeatالكود المنفذ في حدث Heartbeat

للحصول على مزيد من المعلومات حول تصحيح السكربتات باستخدام MicroProfiler، انظر إلى مكتبة debug، التي تتضمن وظائف لوضع علامات على كود محدد وزيادة التحديد بشكل أكبر، مثل debug.profilebegin و debug.profileend. تحتوي العديد من طرق API الخاصة بروبلكس المستدعاة بواسطة السكربتات أيضًا على علامات MicroProfiler الخاصة بها والتي يمكن أن توفر إشارة مفيدة.

استخدام ذاكرة السكربت

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

تدل القيم التالية للذاكرة في وحدة التحكم للمطور على مشكلة تحتاج إلى مزيد من التحقيق:

  • LuaHeap - تشير الاستهلاكات العالية أو المتزايدة إلى وجود تسرب في الذاكرة.
  • InstanceCount - يشير العدد المتزايد باستمرار من المثيلات إلى أن الإشارات لبعض المثيلات في الكود الخاص بك لا يتم جمعها من القمامة.
  • PlaceScriptMemory - يوفر تفصيلًا لاستخدام الذاكرة لكل سكربت.

المشاكل الشائعة

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

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

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

    مثال

    local playerInfo = {}
    Players.PlayerAdded:Connect(function(player)
    playerInfo[player] = {} -- بعض المعلومات
    end)

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

التخفيف

لتنظيف جميع القيم المستخدمة لمنع تسريبات الذاكرة:

  • فصل جميع الاتصالات - قم بمراجعة قاعدة الشيفرة الخاصة بك وتأكد من أن كل اتصال تم تنظيفه عبر واحد من المسارات التالية:

    • فصل يدويًا باستخدام دالة Disconnect().
    • تدمير المثيل الذي ينتمي إليه الحدث باستخدام دالة Destroy().
    • تدمير كائن السكربت الذي يتتبع الاتصال.
  • إزالة كائنات اللاعب والشخصيات بعد مغادرتهم - قم بتمكين Workspace.PlayerCharacterDestroyBehavior لتدمير كائنات اللاعب ونماذج الشخصيات تلقائيًا بعد مغادرة المستخدم. إذا كنت تفضل، يمكنك بدلاً من ذلك تنظيفها يدويًا:

    مثال لتنظيف اللاعب والشخصية

    local Players = game:GetService("Players")
    Players.PlayerAdded:Connect(function(player)
    player.CharacterRemoving:Connect(function(character)
    task.defer(character.Destroy, character)
    end)
    end)
    Players.PlayerRemoving:Connect(function(player)
    task.defer(player.Destroy, player)
    end)

حسابات الفيزياء

يمكن أن يكون محاكاة الفيزياء المفرطة سببًا رئيسيًا لزيادة وقت الحساب لكل إطار على كل من الخادم والعميل.

المشاكل الشائعة

  • تكرار وقت خطوة الفيزياء المفرط - افتراضيًا، يكون سلوك الخطوات في وضع تكييفي، حيث يتم الحصول على خطوات الفيزياء في 60 هرتز أو 120 هرتز أو 240 هرتز، اعتمادًا على تعقيد الآلية الفيزيائية.

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

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

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

التخفيف

  • تثبيت الأجزاء التي لا تتطلب محاكاة - قم بتثبيت جميع الأجزاء التي لا تحتاج إلى العمل بالفيزياء، مثل الشخصيات الثابتة.

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

  • تقليل تعقيد الآلية

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

    • بالنسبة للكائنات الصغيرة أو غير القابلة للتفاعل حيث من النادر أن يلاحظ المستخدمون الفرق، استخدم دقة الصندوق.

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

    • بالنسبة للكائنات الكبيرة والمعقدة جدًا، قم بإنشاء تصادمات مخصصة باستخدام أجزاء غير مرئية عند الإمكان.

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

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

      بدلاً من ذلك، يمكنك تطبيق فلتر CollisionFidelity=PreciseConvexDecomposition على استكشاف الذي يظهر عدد أجزاء الشبكة بدقة دقيقة ويسمح لك بتحديدها بسهولة.

    • للحصول على نظرة مفصلة حول كيفية اختيار خيار دقة الاصطدام التي توازن بين متطلبات دقتك وأداءك، راجع تعيين معلمات الفيزياء والتصوير.

مجالات MicroProfiler

النطاقالحساب المرتبط
physicsSteppedإجمالي حسابات الفيزياء
worldStepخطوات الفيزياء المنفصلة المتخذة في كل إطار

استخدام ذاكرة الفيزياء

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

المشكلة الشائعة

تستهلك أوضاع الكشف الافتراضية والدقيقة للاصطدام ذاكرة أكبر بكثير من وضعي الكشف الآخرين مع أشكال الاصطدام الأقل دقة.

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

كيفية التخفيف

لتقليل الذاكرة المستخدمة لدقة الاصطدام:

  • بالنسبة للأجزاء التي لا تحتاج إلى الاصطدامات، قم بتعطيل الاصطدامات عنها عن طريق تعيين BasePart.CanCollide و BasePart.CanTouch و BasePart.CanQuery إلى false.
  • قلل دقة الاصطدام باستخدام إعداد CollisionFidelity. يتمتع Box بأقل تكاليف ذاكرة، بينما يعتبر Default و Precise عادةً أكثر تكلفة.
    • من الآمن عمومًا ضبط دقة الاصطدام لأي جزء صغير مثبت على Box.
    • بالنسبة للشبكات الكبيرة جدًا والمعقدة، قد ترغب في بناء شبكتك الخاصة من كائنات أصغر ذات دقة الاصطدام الصندوقية.

البشر

Humanoid هو فئة توفر مجموعة واسعة من الوظائف لشخصيات اللاعبين وغير اللاعبين (NPCs). على الرغم من قوتها، فإن Humanoid يأتي بتكلفة حسابية كبيرة.

المشاكل الشائعة

  • ترك جميع HumanoidStateTypes مفعلًا على NPCs - توجد تكلفة أداء لإبقاء بعض HumanoidStateTypes مفعلين. قم بتعطيل أي منها ليست بالواجهة لنشاط NPC الخاص بك. على سبيل المثال، ما لم يكن من مقرر لنشاط NPC الخاص بك تسلق السلالم، من الآمن تعطيل حالة Climbing.
  • إنشاء، تعديل، وإعادة إحياء نماذج باستخدام Humanoids أو MeshParts بشكل متكرر
    • يمكن أن يكون هذا مكلفًا بالنسبة للمحرك لمعالجته، خصوصًا إذا كانت هذه النماذج تستخدم ملابس متعددة الطبقات. يمكن أن تكون هذه المشكلة حادة بشكل خاص في الألعاب التي غالبًا ما ينسل فيها الأفاتار.
    • في MicroProfiler، تعمل علامات updateInvalidatedFastClusters الطويلة (أكثر من 4 مللي ثانية) غالبًا كإشارة تشير إلى أن خلق أو تعديل الأفاتار يؤدي إلى تقديم إلغاءات مفرطة.
  • استخدام البشر في حالات لا تُعتبر ضرورية - عادة ما لا تحتاج NPCs الثابتة التي لا تتحرك إلى كائن Humanoid.
  • تشغيل الرسوم المتحركة على عدد كبير من NPCs من الخادم - تحتاج الرسوم المتحركة لـ NPC التي تعمل على الخادم إلى محاكاة على الخادم وتكرارها إلى العميل. يمكن أن تكون هذه تكلفة غير ضرورية.
  • إجراء تغييرات غير ضرورية على الحجم والمقياس - تسبب تغييرات الحجم/المقياس إعادة بناء FastCluster. حاول تقليل ذلك أثناء اللعب إذا كنت تواجه قضايا أداء تتعلق بـ FastCluster. بنفس الطريقة، قد تتسبب تغييرات الخصائص الأخرى أيضًا في إعادة بناء FastCluster، لذا بشكل عام قلل هذه التغييرات قدر الإمكان.

التخفيف

  • قم بتشغيل رسوم متحركة NPC على العميل - في الألعاب التي تحتوي على عدد كبير من NPCs، ضع في اعتبارك إنشاء Animator على العميل وتشغيل الرسوم المتحركة محليًا. يقلل ذلك من الحمل على الخادم ويزيل الحاجة إلى النسخ غير الضروري. كما أنه يجعل من الممكن إجراء تحسينات إضافية (مثل تشغيل الرسوم المتحركة فقط للكائنات القريبة من الشخصية).
  • استخدم بدائل صديقة للأداء للبشر - لا تحتاج نماذج NPCs بالضرورة إلى أن تحتوي على كائن بشري.
    • بالنسبة لـ NPCs الثابتة، استخدم AnimationController بسيطة، لأنها لا تحتاج إلى التحرك ولكن تحتاج فقط إلى تشغيل الرسوم المتحركة.
    • بالنسبة لـ NPCs المتحركة، ضع في اعتبارك تنفيذ وحدة التحكم الخاصة بك للحركة واستخدام AnimationController للرسوم المتحركة، اعتمادًا على تعقيد NPCs الخاصة بك.
  • تعطيل حالات الإنسان غير المستخدمة - استخدم Humanoid:SetStateEnabled() لتمكين فقط الحالات الضرورية لكل إنسان.
  • تجميع نماذج NPC التي تُعيد إحيائها بشكل متكرر - بدلاً من تدمير NPC بالكامل، أرسل الـ NPC إلى مجموعة من NPCs غير النشطة. بهذه الطريقة، عندما يتطلب الأمر إعادة إنشاء NPC جديدة، يمكنك ببساطة تفعيل أحد الـ NPCs من المجموعة. هذه العملية تُسمى التجميع، والتي تقلل من عدد مرات الحاجة لإنشاء شخصيات جديدة.
  • يمكنك فقط إنشاء NPCs عندما يكون المستخدمون قريبين - لا تقم بإنشاء NPCs عندما لا يكون المستخدمون في النطاق، وقطع الاتصال بهم عندما يغادر المستخدمون نطاقهم.
  • تجنب إجراء تغييرات على التسلسل الهيكلي للأفاتار بعد إنشائه - يمكن أن تؤدي تغييرات معينة على التسلسل الهيكلي للأفاتار إلى تأثيرات ملحوظة. بعض التحسينات متاحة:
    • بالنسبة للرسوم المتحركة الإجرائية المخصصة، لا تقم بتحديث خصائص JointInstance.C0 و JointInstance.C1. بدلاً من ذلك، قم بتحديث خاصية Motor6D.Transform.
    • إذا كنت بحاجة إلى ربط أي كائنات BasePart بالأفاتار، قم بذلك خارج تسلسل هيكل الأفاتار.

مجالات MicroProfiler

النطاقالحساب المرتبط
stepHumanoidالتحكم في البشر والفيزياء
stepAnimationالرسوم المتحركة للبشر والرسوم المتحركة
updateInvalidatedFastClustersمرتبطة بإنشاء أو تعديل شخصية

التصوير

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

استدعاءات الرسم

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

يمكنك رؤية عدد استدعاءات الرسم التي تحدث حاليًا من خلال خيار إحصائيات التصويرالتوقيت في الاستوديو. يمكنك عرض إحصائيات التصوير في العميل بالضغط على ShiftF2.

كلما زادت الكائنات التي تحتاج إلى الرسم في مشهدك في إطار معين، زادت استدعاءات الرسم المصنوعة للتوصيل. ومع ذلك، يستخدم Roblox Engine عملية تُدعى التماثل لتقليل الشبكات المتطابقة ذات الخصائص المختلفة وتعالجها في استدعاء رسم واحد. على وجه الخصوص، يتم التعامل مع أجزاء الشبكة المتعددة التي تحمل نفس MeshContent في استدعاء رسم واحد عندما:

المشاكل الشائعة الأخرى

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

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

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

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

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


    for _,descendant in workspace:GetDescendants() do
    if descendant:IsA("MeshPart") then
    print(descendant.Name .. ", " .. descendant.MeshId)
    end
    end

    قد يبدو الناتج (مع تمكين Stack Lines) شيئًا كهذا. تشير الأسطر المكررة إلى إعادة استخدام نفس الشبكة، وهو أمر جيد. ليست الأسطر الفريدة بالضرورة سيئة، ولكن اعتمادًا على نظام التسمية الخاص بك، يمكن أن تشير إلى نسخ مكررة في لعبتك:


    LargeRock, rbxassetid://106420009602747 (x144) -- جيد
    LargeRock, rbxassetid://120109824668127
    LargeRock, rbxassetid://134460273008628
    LargeRock, rbxassetid://139288987285823
    LargeRock, rbxassetid://71302144984955
    LargeRock, rbxassetid://90621205713698
    LargeRock, rbxassetid://113160939160788
    LargeRock, rbxassetid://135944592365226 -- جميع النسخ الممكنة
  • تعقيد الكائن المفرط - على الرغم من عدم أهمية عدد استدعاءات الرسم، إلا أن عدد المثلثات في المشهد يؤثر على المدة التي يستغرقها الإطار لكى يتم رسمه. يُعتبر وجود مشاهد تحتوي على عدد كبير جدًا من الشبكات المعقدة مشكلة شائعة، كما أن المشاهد التي يتم تعيين خاصية MeshPart.RenderFidelity على Precise على العديد من الشبكات.

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

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

  • حركة أجزاء الشبكة المكسوة غير الضرورية - أجزاء الشبكة المكسوة التي هي جزء من نموذج بدون بشر يتم تجميعها باستخدام FastClusters المعالجة مكانيًا. عندما تتحرك هذه الأجزاء، يجب إضافتها وإزالتها باستمرار من هذه الكتل المكانية، مما يجبر الكتل على إعادة البناء ويؤثر على الأداء.

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

التخفيف

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

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

  • تقليل مستوى تفاصيل النماذج - قم بتمكين تدفق الكائنات واضبط خاصية LevelOfDetail لنماذج العالم الخاص بك على SLIM لرسم شبكات SLIM المحسّنة كلما زادت المسافة عن الكاميرا.

  • تقليل مستوى تفاصيل الأفاتار - قم بتمكين تدفق الكائنات واضبط خاصية Workspace.EnableSLIMAvatars لرسم نماذج الأفاتار على المنصة مع عدد غير محدود من الملحقات أو طبقات الملابس كنماذج أفاتار خفيفة الوزن محسّنة مع دعم كامل للرسوم المتحركة عند زيادة المسافة عن الكاميرا.

  • تقليل دقة الرسم - اضبط MeshPart.RenderFidelity إلى Automatic أو Performance. هذا يسمح للشبكات بالعودة إلى بدائل أقل تعقيدًا، مما يمكن أن يقلل من عدد المضلعات التي يجب رسمها.

  • تعطيل إلقاء الظلال على الأجزاء وكائنات الضوء المناسبة - يقوم محرك روبيليكس تلقائيًا بتقليل جودة الظلال كلما انخفض مستوى جودة الرسومات على العميل، وعندما تقلّ المستويات عن 4، يتم تعطيل الظلال تمامًا. ومع ذلك، يمكنك التعطيل الانتقائي لخصائص إلقاء الظلال على كائنات الضوء والأجزاء لتحسين الأداء في حين أن الظلال مفعلّة وزيادة فرص بقاء الظلال مفعلة. بعض الأمثلة على التحسينات التي يمكنك إجراؤها إما في الوقت الذي تُحرر فيه أو ديناميكيًا أثناء التنفيذ:

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

    • تعطيل الظلال على الكائنات المتحركة متى أمكن.

    • تعطيل Light.Shadows على العينات الضوئية حيث لا يحتاج الكائن إلى إلقاء الظلال.

    • الحد من نطاق وزاوية العينات الضوئية.

    • استخدام عدد أقل من العينات الضوئية.

    • التفكير في تعطيل الأضواء التي تكون خارج نطاق معين أو على أساس غرفة بغرفة في البيئات الداخلية.

مجالات MicroProfiler

النطاقالحساب المرتبط
Prepare and Performإجمالي التصوير
Perform/Scene/computeLightingPerformتحديث الشبكة الضوئية وتحديثات الظل
LightGridCPUتحديثات شبكة الضوء الفوكسي
ShadowMapSystemتخطيط الظل
Perform/Scene/UpdateViewإعداد للرسم وتحديثات الجسيمات
Perform/Scene/RenderViewالرسم ومعالجة ما بعد الرسم

الشبكات والتكرار

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

المشاكل الشائعة

  • حركة مفرطة عبر الشبكة - يمكن أن تؤدي إرسال كميات كبيرة من البيانات عبر RemoteEvent أو RemoteFunction أو استدعائها بشكل متكرر جدًا إلى إنفاق كمية كبيرة من وقت وحدة المعالجة المركزية في معالجة الحزم الواردة في كل إطار. تشمل الأخطاء الشائعة:

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

    سبب شائع هنا هو البيانات المتحركة المعقدة المحفوظة بواسطة مكونات Animation Editor في النماذج. إذا لم تتم إزالتها قبل نشر اللعبة وتم استنساخ النموذج المتحرك بشكل متكرر، سيتم تكرار كمية كبيرة من البيانات بشكل غير ضروري.

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

التخفيف

يمكنك استخدام التكتيكات التالية لتقليل النسخ غير الضروري:

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

مجالات MicroProfiler

النطاقالحساب المرتبط
ProcessPacketsمعالجة حزم الشبكة الواردة، مثل استدعاءات الأحداث وتغييرات الخصائص
Allocate Bandwidth and Run Sendersالأحداث الصادرة ذات الصلة على الخوادم

استخدام ذاكرة الأصول

آلية التأثير الأعلى المتاحة للمبدعين لتحسين استخدام ذاكرة العميل هي تمكين تدفق العينات.

تدفق العينات

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

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

إذا تم تمكين تدفق العينات، يمكنك زيادة حدته. على سبيل المثال، اعتبر:

  • تقليل استخدام Enum.ModelStreamingMode.Persistent حيثما كان ذلك ممكنًا. قد تحتاج إلى تحديث السكربتات الخاصة بك إذا كنت تستخدمها كإجراء احتياطي.
  • تقليل Workspace.StreamingMinRadius و Workspace.StreamingTargetRadius.

للحصول على مزيد من المعلومات حول خيارات التدفق وفوائدها، راجع خصائص التدفق.

مشاكل شائعة أخرى

  • تكرار الأصول - خطأ شائع هو رفع نفس الأصل عدة مرات مما يؤدي إلى معرفات أصول مختلفة. يمكن أن يؤدي هذا إلى تحميل نفس المحتوى في الذاكرة عدة مرات.

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

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

  • الملمس العالي الدقة - لا يكون استهلاك الذاكرة الرسومية لملمس غير مرتبط بحجم الملمس على القرص؛ بل إن عدد البكسلات في الملمس يحدد استخدام الذاكرة. على سبيل المثال، يستهلك ملمس بحجم 1024x1024 بكسل أربع مرات من الذاكرة الرسومية أكثر من ملمس 512x512 بكسل.

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

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

التخفيف

  • رفع الأصول مرة واحدة فقط - إعادة استخدام نفس معرف الأصل عبر الكائنات وتأكد من أن نفس الأصول، خاصةً الشبكات والصور، ليست مُحملة بشكل منفصل عدة مرات.

  • البحث عن الأصول المكررة وإصلاحها - ابحث عن أجزاء الشبكات المماثلة والنقوش التي تم تحميلها عدة مرات بمعرفات مختلفة.

    • على الرغم من عدم وجود API للكشف عن تشابه الأصول تلقائيًا، يمكنك جمع جميع معرفات أصول الصور في مكانك (يدويًا أو باستخدام سكربت)، الوصول إليها وتنزيلها، ومقارنتها باستخدام أدوات مقارنة خارجة.
    • بالنسبة لأجزاء الشبكة، فإن أفضل استراتيجية هي أخذ معرفات الشبكة الفريدة وتصنيفها حسب الحجم لتحديد التكرارات يدويًا.
    • بدلاً من استخدام نقوش منفصلة لألوان مختلفة، قم برفع نقش واحد واستخدم خاصية SurfaceAppearance.Color لتطبيق ألوان مختلفة عليه.
  • استيراد الأصول في الخريطة بشكل منفصل - بدلاً من استيراد خريطة كاملة مرة واحدة، استورد وأعد بناء الأصول في الخريطة بشكل فردي وأعد تجميعها. لا يقوم المستورد بأي إزالة للأصول المكررة، لذا إذا قمت باستيراد خريطة كبيرة بها الكثير من بلاط الأرضيات المنفصلة، سيتم استيراد كل من هذه البلاط كأصل منفصل (حتى لو كانت تكرارات). يمكن أن يؤدي ذلك إلى مشاكل في الأداء والذاكرة في المستقبل، حيث يُعامل كل شبكة على أنها فردية وتشغل ذاكرة واستدعاءات رسم.

  • تحديد عدد بكسلات الصور إلى الحد الأقصى الضروري فقط. إلا إذا كانت الصورة تشغل مساحة كبيرة من المادي على الشاشة، فعادةً ما تحتاج إلى 512x512 بكسل على الأكثر. يجب أن تكون معظم الصور الصغيرة أقل حجمًا من 256x256 بكسل.

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

    يمكنك أيضًا التفكير في استخدام جداول الرموز لتحميل العديد من الصور الصغيرة لواجهة المستخدم كصورة واحدة. يمكنك بعد ذلك استخدام ImageLabel.ImageRectOffset و ImageLabel.ImageRectSize لعرض أجزاء من الجدول.

أوقات التحميل

تنفذ العديد من الألعاب شاشات تحميل مخصصة وتستخدم طريقة ContentProvider:PreloadAsync() لطلب الأصول حتى يتم تنزيل الصور، والأصوات، والشبكات في الخلفية.

تتمثل ميزة هذه الطريقة في أنها تتيح لك التأكد من أن الأجزاء المهمة من لعبتك قد تم تحميلها بالكامل دون وجود `` pop-in. ومع ذلك، فإن الخطأ الشائع هو الإفراط في استخدام هذه الطريقة لتحميل أكثر من الأصول المطلوبة بالفعل.

مثال على ممارسة سيئة هو تحميل Workspace بالكامل. بينما قد يمنع ذلك `` pop-in من الملمس، فإنه يزيد بشكل كبير من أوقات التحميل.

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

بدلاً من ذلك، استخدم فقط ContentProvider:PreloadAsync() في المواقف الضرورية، بما في ذلك:

  • الصور في شاشة التحميل.
  • الصور المهمة في قائمة اللعب، مثل خلفيات الأزرار والرموز.
  • الأصول المهمة في منطقة البدء أو التوليد.

إذا كان يجب عليك تحميل عدد كبير من الأصول، نقترح عليك توفير زر تخطي التحميل.

©2026 شركة Roblox Corporation. تُعد منصّة Roblox، وشعار Roblox وشعار "توسيع حدود المخيلة"، من ضمن علاماتنا التجارية المسجّلة وغير المسجّلة في الولايات المتحدة وبلدان أخرى.