سؤال

لم أقم ببرمجة الألعاب منذ حوالي 10 سنوات (كانت تجربتي الأخيرة هي DJGPP + Allegro)، لكنني اعتقدت أنني سأقوم بمراجعة XNA خلال عطلة نهاية الأسبوع لأرى كيف كانت تتشكل.

أنا معجب إلى حد ما، ولكن مع استمراري في تجميع محرك اللعبة، لدي سؤال أساسي (على الأرجح).

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

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

  • لديك طريقة "UpdateCameras()" في حلقة اللعبة الرئيسية.
  • استخدم معالج الأحداث، واطلب من كاميرا المطاردة الاشتراك في object.OnMoved.

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

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

أفكار؟

هل كانت مفيدة؟

المحلول

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

إذا كنت تريد أن تكون التعليمات البرمجية الخاصة بك عامة أو ديناميكية، فستحتاج إلى التحقق مما إذا كان هناك شيء مشترك قبل الاتصال بحدث ما.آلية الحدث/التفويض في C# و.NET توفر لك ذلك بتكلفة قليلة جدًا (فيما يتعلق بوحدة المعالجة المركزية).

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

مكتوبًا بشكل جيد، أفضّل الأحداث/المندوبين حتى أتمكن من إثبات أنها مشكلة.

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

نصائح أخرى

من المهم أن تدرك أن الأحداث في C# ليست أحداثًا غير متزامنة في قائمة الانتظار (مثل قائمة انتظار رسائل Windows على سبيل المثال).وهي في الأساس قائمة من المؤشرات الوظيفية.لذا فإن رفع حدث ليس له آثار أسوأ على الأداء من التكرار من خلال قائمة مؤشرات الوظائف واستدعاء كل منها.

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

ويبدو أن السؤال الرئيسي هنا هو:"ما هو الحمل المرتبط باستخدام C# Delegates and Events؟"

الأحداث لها حمل كبير قليل بالمقارنة مع استدعاء دالة عادية.

يمكن أن يؤدي استخدام المندوبين إلى إنشاء نفايات ضمنية وبالتالي مخفية.يمكن أن تكون النفايات سببًا رئيسيًا لمشاكل الأداء خاصة على XBox360.

ينشئ التعليمة البرمجية التالية حوالي 2000 بايت من البيانات المهملة في الثانية (بمعدل 60 إطارًا في الثانية) في شكل كائنات EntityVisitor:

    private delegate void SpacialItemVisitor(ISpacialItem item);

    protected override void Update(GameTime gameTime)
    {
        m_quadTree.Visit(ref explosionCircle, ApplyExplosionEffects);
    }

    private void ApplyExplosionEffects(ISpacialItem item)
    {
    }

طالما أنك تتجنب توليد البيانات المهملة، فإن المفوضين يتمتعون بالسرعة الكافية لمعظم الأغراض.بسبب المخاطر الخفية، أفضّل تجنبها واستخدام الواجهات بدلاً من ذلك.

وفي الوقت الإضافي الذي أقضيه بعيدًا عن العمل الحقيقي، كنت أتعلم XNA أيضًا.

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

لأكون صادقًا، أعتقد أن الانتقال إلى طريقة UpdateCameras قد يكون تحسينًا سابقًا لأوانه.من المحتمل أن يكون لنظام الأحداث استخدامات أخرى غير الكاميرا.

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

الجواب هو "بقدر ما تشعر بالراحة معه".

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

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

إليك مثال على ذلك (جميع دروسه ممتازة):كود ريو

جانبا، قد تكون مهتما بمعرفة ذلك شون هارجريفز, المطور الأصلي لـ أليجرو, ، هو أحد المطورين الرئيسيين في فريق XNA :-)

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

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

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

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

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top