في محادثات Pixonic DevGAMM ، تحدث أيضًا DTO Anton Grigoriev. لقد قلنا في الشركة بالفعل أننا نعمل على مطلق النار PvP الجديد وشارك أنطون بعض الفروق الدقيقة في هندسة هذا المشروع. أخبر كيفية بناء التطوير بحيث تظهر التغييرات في منطق لعبة العميل على الخادم تلقائيًا (والعكس صحيح) ، وما إذا كان من الممكن عدم كتابة التعليمات البرمجية ، ولكن تقليل حركة المرور. يوجد أدناه سجل ونسخة من التقرير.
لن أتعلم كيف أفعل شيئًا ، سأتحدث عن كيف فعلنا ذلك. حتى لا تخطو على نفس أشعل النار وتستطيع استخدام خبرتنا. قبل عام ونصف ، لم نكن في الشركة نعرف كيف نصنع الرماة على الهواتف المحمولة. تقول كيف ، لديك War Robots ، 100 مليون تنزيل ، 1.5 مليون DAUs. لكن في هذه اللعبة ، الروبوتات بطيئة جدًا ، وأردنا أن نصنع مطلقًا سريعًا ، ولم تسمح هندسة War Robots بذلك.
كنا نعرف كيف وماذا نفعل ، ولكن لم يكن لدينا خبرة. ثم استأجرنا شخصًا لديه هذه التجربة وقلنا: افعل نفس الشيء الذي فعلته بالفعل مائة مرة ، أفضل فقط. ثم جلسوا وبدأوا يفكرون في الهندسة المعمارية.

جاء إلى نظام مكونات الكيان (ECS). أعتقد أن الكثير من الناس يعرفون ما هو. يتم تمثيل جميع الأشياء في العالم من قبل الكيانات. على سبيل المثال ، لاعب ، بندقيته ، شيء ما على الخريطة. لديهم خصائص تم وصفها بواسطة المكونات. على سبيل المثال ، مكون التحويل هو موضع اللاعب في الفضاء ، والمكون الصحي هو صحته. هناك منطق - إنه منفصل ويمثله النظم. عادةً ما تكون الأنظمة هي طريقة Execute () ، التي تمر عبر مكونات من نوع معين وتقوم بعمل شيء معها ، مع عالم اللعبة. على سبيل المثال ، يتحرك MoveSystem في جميع مكونات الحركة ، وينظر إلى السرعة في هذا المكون ، والمعلمة وعلى أساس هذا يحسب الموضع الجديد للكائن ، أي يكتبه لتحويل.
هذه الهندسة المعمارية لها خصائصها الخاصة. عند التطوير على ECS ، تحتاج إلى التفكير والقيام بالأشياء بشكل مختلف. واحدة من الإيجابيات هي التكوين بدلاً من الميراث المتعدد. هل تتذكر هذه المعينية ذات الميراث المتعدد في C ++؟ كل مشاكله. ليس هذا هو الحال في ECS.

السمة الثانية هي فصل المنطق والبيانات ، التي تحدثت عنها بالفعل. ماذا يعطينا هذا؟ يمكننا تخزين حالة العالم وتاريخها على دفعات ، يمكننا إجراء تسلسل لها ، يمكننا إرسال هذه البيانات عبر الشبكة وتغييرها في الوقت الفعلي. هذه مجرد بيانات في الذاكرة - يمكننا تغيير أي قيمة في أي وقت. وبالتالي ، من المناسب جدًا تغيير منطق اللعبة (أو التصحيح).
من المهم أيضًا تتبع ترتيب استدعاء النظام. جميع الأنظمة تسير واحدة تلو الأخرى ، ويتم استدعاؤها بواسطة طريقة Execute () ، ومن الأفضل أن تكون مستقلة. عمليا ، هذا لا يحدث. يقوم أحد الأنظمة بتغيير شيء ما في العالم ، ثم يستخدمه نظام آخر. وإذا كسرنا هذا الأمر ، فستسير اللعبة بشكل مختلف. ربما ليس كثيرًا ، ولكن بالتأكيد ليس كما كان من قبل.
أخيرًا ، تتمثل إحدى الميزات الرئيسية والأكثر أهمية بالنسبة لنا في أنه يمكننا تنفيذ نفس التعليمات البرمجية على كل من العميل والخادم.
امنح المطور فرصة ، وسيجد 99 طريقة وأسبابًا لاتخاذ قراره ، وعدم استخدام الطرق الموجودة. أعتقد أن الكثيرين فعلوا ذلك. كنا نبحث عن إطار عمل ECS في ذلك الوقت. اعتبرنا Entitas و Artemis C # و Ash.net والحل الخاص بنا ، والذي يمكن كتابته من تجربة أخصائي جاء إلينا.

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

اتضح أن النسخة غير قابلة للتشغيل. اللاعب يتراجع باستمرار ، الفرامل ، علق الخادم في منتصف المباراة. كان من المستحيل لعبها. ما هي أسباب الفشل؟
السبب رقم 1 والأهم هو عدم الخبرة. لكن كيف ذلك؟ قمنا بتوظيف شخص متمرس كان من المفترض أن يقوم بكل شيء بشكل جميل. نعم ، ولكن في الحقيقة لم نمنحه سوى جزء من العمل. قلنا: "إليك خادم ألعاب ، اعمل عليه". وفي هندستنا (المزيد عن هذا لاحقًا) ، يلعب العميل دورًا مهمًا للغاية. وكان هذا الجزء الذي قدمناه لرجل لم يكن لديه الخبرة اللازمة. لا ، إنه مبرمج جيد ، سنور - ببساطة لم تكن هناك خبرة. على سبيل المثال لم يكن لديه أي فكرة عن نوع أشعل النار الذي قد يكون هناك.
السبب # 2 - تخصيصات غير واقعية. 80 كيلوبايت / الإطار. هل هو كثير ام لا؟ إذا أخذنا في الاعتبار أن لدينا 30 إطارًا في الثانية ، فإننا نحصل في الثانية على 2.5 ميجابايت ، وللمباراة لمدة 5 دقائق ، يوجد بالفعل أكثر من 600 ميجابايت. باختصار ، الكثير. يبدأ جامع القمامة في محاولة مكثفة لتحرير كل هذه الذاكرة (عندما نطلب المزيد والمزيد منها) ، مما يؤدي إلى طفرات. نظرًا لأننا أردنا 30 إطارًا في الثانية ، فقد تدخلت هذه المسامير فينا كثيرًا. علاوة على ذلك ، سواء على العميل وعلى الخادم.
كان السبب الرئيسي للتخصيصات هو أننا خصصنا باستمرار صفائف البيانات. في كل مرة تقريبًا كل إطار. تستخدم عبارات LINQ و lambda و الفوتون. الفوتون هي مكتبة شبكية نعرفها ونستخدمها في War Robots. ويبدو أن كل شيء على ما يرام ، ولكنه يخصص ذاكرة في كل مرة يرسل فيها البيانات أو يستقبلها.
إذا قمنا بفرز المشاكل الأولى (إعادة كتابة مجموعاتنا المخصصة ، وقمنا بالتخزين المؤقت) ، فعندئذ لا يوجد شيء يمكن القيام به باستخدام الفوتون ، لأنه مكتبة تابعة لجهة خارجية. كان من الممكن فقط تقليل حجم الحزمة ، وكان لدينا 5 كيلوبايت. الكثير؟ نعم يوجد MTU - هذا هو الحد الأدنى لحجم الحزمة الفعلي الذي يتم إرساله عبر UDP ، دون تقسيم الحزمة إلى أجزاء صغيرة. إنه تقريبًا 1.5 كيلوبايت ، وكان لدينا 5 (في المتوسط ، كان هناك المزيد).
وفقا لذلك ، قطع الفوتون مجموعتنا إلى مجموعات صغيرة وأرسل كل قطعة كموثوق بها ، أي مع تسليم مضمون. في كل مرة لم يصل الجزء ، كان يرسلها مرارا وتكرارا. حصلنا على مزيد من الكمون وعملت الشبكة بشكل سيئ.
أدت جميع هذه التخصيصات إلى حقيقة أننا تلقينا إطارًا يبلغ حوالي 100 مللي ثانية عند الحاجة إلى 33. وهناك ، تقديم ومحاكاة وإجراءات أخرى - كل هذا يتطلب وحدة المعالجة المركزية. كل هذه المشاكل معقدة ، أي كان من المستحيل تحديد واحد ، وسيكون كل شيء على ما يرام. كان من الضروري حلها كلها في وقت واحد.
ومشكلة صغيرة أخرى كانت أثناء التطوير - عدد كبير من المستودعات. 5 مكتوب على الشريحة ، ولكن يبدو لي أنه كان هناك المزيد منها. تم ربط جميع هذه المستودعات (للعميل وخادم اللعبة والرمز المشترك والإعدادات وشيء آخر) بواسطة وحدات فرعية في المستودعين الرئيسيين للعميل وخادم اللعبة. كان من الصعب العمل معه. يمكن للمبرمجين العمل مع Git و SVN ، ولكن هناك أيضًا فنانين ومصممين وما إلى ذلك. أعتقد أن الكثيرين حاولوا تعليم فنان أو مصمم كيفية العمل مع نظام التحكم في الإصدار. هذا صعب حقًا ، لذلك إذا كان مصممك يعرف كيفية القيام بذلك - اعتن به ، فهو موظف قيم. في حالتنا ، حتى المبرمجين خافوا ، ونتيجة لذلك ، قمنا بتقليل كل شيء إلى مستودع واحد.
كان هذا حلاً رائعًا للمشكلة. لدينا مجلد مع خادم هناك ومجلد مع عميل. يتكون الخادم من مشروع خادم ألعاب ومولد تعليمات برمجية وأدوات مساعدة.

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

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

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

سبق أن قلت أن لدينا مولد أكواد في خادم ألعاب. هناك لغة خاصة بالمجال ، وهي في الواقع فئة C # بسيطة. في هذه الحالة ، فئة الصحة. نحن نميزها بصفاتنا. على سبيل المثال ، هناك سمة مكون. يقول أن الصحة هي عنصر في عالمنا. بناءً على هذه السمة ، سينشئ المولد فئة C # جديدة حيث سيكون هناك مجموعة من الأشياء. يمكن كتابتها يدويًا ، ولكنها ستولد. على سبيل المثال ، طريقة إضافة مكون إلى الكيان ، طريقة البحث عن المكونات ، تسلسل البيانات ، إلخ. هناك سمة من نوع DontSend ، والتي تقول أنه ليس من الضروري إرسال حقل عبر الشبكة - لا يحتاج الخادم إليه أو لا يحتاجه العميل. أو السمة ماخ التي تشير إلى أن اللاعب لديه قيمة صحية قصوى تبلغ ألف. ماذا يعطينا هذا؟ بدلاً من حقل يشغل 32 بت (int) ، نرسل 10 بتات - ثلاث مرات أقل. سمح لنا مولد الشفرة هذا بتقليل حجم الحزمة من 5 كيلوبايت إلى 1.

1 كيلوبايت <1.5 - بمعنى التقينا MTU. توقف الفوتون عن القطع وتحسنت الشبكة كثيرًا. لقد ذهبت كل مشاكلها تقريبًا. لكننا ذهبنا أبعد من ذلك وقمنا بضغط دلتا.

هذا عندما ترسل حالة واحدة كاملة ، ثم فقط تغييراتها. لا يحدث أن العالم كله تغير على الفور بالكامل. فقط بعض الأجزاء تتغير باستمرار وهذه التغييرات أصغر في الحجم من الدولة نفسها. تلقينا ما معدله 300 بايت ، أي 17 مرة أقل مما كانت عليه في الأصل.
لماذا هذا ضروري إذا كنت قد دخلت بالفعل إلى MTU؟ اللعبة تنمو باستمرار ، وتظهر ميزات جديدة ، ومعها تظهر أشياء ، كيان ، مكونات جديدة. حجم البيانات ينمو. إذا توقفنا عند 1 كيلوبايت ، فسنعود قريبًا إلى نفس المشكلة. الآن ، بعد إعادة كتابته لضغط دلتا ، لن نصل إلى هذا قريبًا.
الآن أحلى جزء. تزامن إذا كنت تلعب الرماة ، فأنت تعرف ما هو Input Lag - عندما تنقر على الزر ، وتبدأ الشخصية في التحرك بعد مرور بعض الوقت ، على سبيل المثال ، نصف ثانية. بالنسبة لبعض الألعاب في نوع الغوغاء ، يعد هذا أمرًا طبيعيًا. ولكن في مطلق النار ، تريد من البطل إطلاق النار وإلحاق الضرر هناك.

لماذا يحدث تأخر الإدخال؟ يقوم العميل بتجميع مدخلات اللاعب (الإدخال) وإرسالها إلى خادم اللعبة (تستغرق عملية الإرسال وقتًا). ثم يعالجها خادم اللعبة (مرة أخرى ، مرة) ويرسل النتيجة مرة أخرى (مرة أخرى ، مرة). هذا تأخير. كيفية إزالته؟ هناك شيء يسمى التنبؤ - لا ينتظر العميل استجابة من الخادم ويبدأ فورًا في محاولة القيام بنفس الشيء الذي يفعله خادم اللعبة ، أي يتظاهر. يأخذ إدخال اللاعب ويبدأ المحاكاة. نحن نقوم فقط بمحاكاة عميل محلي ، لأننا لا نعرف مدخلات اللاعبين الآخرين - فهم لا يأتون إلينا. لذلك ، نقوم بتشغيل نظام المحاكاة فقط على لاعبنا.
أولاً ، يسمح بتقليل وقت المحاكاة. يبدأ العميل المحاكاة بمجرد أن يتلقى الإدخال ويتقدم عدة خطوات إلى الأمام بالنسبة لخادم اللعبة. لنفترض في هذه الصورة أنه يحاكي العلامة رقم 20. عند هذه النقطة ، يحاكي خادم اللعبة العلامة رقم 15 في الماضي. يرى العميل بقية العالم ، مرة أخرى ، في الماضي ، بنفسه - في المستقبل. بينما يرسل القراد العشرين إلى الخادم ، بينما يصل هذا الإدخال ، سيبدأ خادم اللعبة بالفعل في محاكاة القراد الثامن عشر أو 20 بالفعل. إذا كان الثامن عشر ، فإنه يضعها في المخزن المؤقت ، ويصل إلى العشرين ، ويعالج النتيجة ويعيدها مرة أخرى.
لنفترض الآن أنه يحاكي القراد رقم 15. معالجتها ، إرجاع النتيجة إلى العميل. العميل لديه نوع من القراد 15 محاكاة ، حالة اللعبة 15 وعالم اللعبة الذي تنبأ به. تبدأ المقارنة مع الخادم. في الواقع ، إنه لا يقارن العالم كله ، بل موكله فقط ، لأننا لسنا مسؤولين عن بقية العالم. نحن مسؤولون فقط عن أنفسنا. إذا تزامن اللاعب ، فإن كل شيء على ما يرام ، مما يعني أننا قمنا بالمحاكاة بشكل صحيح ، وعملت الفيزياء بشكل صحيح ولم تنشأ أي تصادمات. ثم نواصل محاكاة القراد العشرين والحادي والعشرين وما إلى ذلك.
إذا لم يتطابق العميل / اللاعب ، فهذا يعني أننا أخطأنا في مكان ما. مثال: بما أن الفيزياء ليست حتمية ، فإنها لم تحسب موقفنا بشكل صحيح أو حدث شيء ما. ربما مجرد خطأ. ثم يأخذ العميل الحالة من خادم اللعبة ، لأن خادم الألعاب أكدها بالفعل (فهو يثق في الخادم - إذا لم يثق ، فسيغش اللاعبون) ، وسيعيد محاكاة الباقي من 15 إلى 20. لأن هذا الفرع الزمني خاطئ الآن.
إنشاء فرع زمني جديد ، أي عوالم موازية. نحن نعيد قياس هذه القراد الخمس في علامة واحدة. بمجرد أن تستغرق المحاكاة 5 مللي ثانية ، ولكن إذا احتجنا إلى محاكاة 10 علامات ، فهذا يعني بالفعل 50 مللي ثانية ولا نقع في 30 مللي ثانية. لقد تم تحسينها وحصلت على مللي ثانية واحدة - الآن تتم معالجة 10 علامات في 10 مللي ثانية. لأنه لا يزال هناك تقديم.
كل هذه الأشياء تعمل على العميل ، وأعطيناها للشخص دون الخبرة اللازمة. ناقص - كان لدينا fakap ، بالإضافة إلى - أن المبرمج يعرف الآن كيف يفعل ذلك بشكل صحيح.

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

لذا ، وصلنا إلى 30 علامة في الثانية ، 30 إطارًا في الثانية. الآن يلعب حوالي 600 لاعب على خادمنا في نفس الوقت. هناك 6 لاعبين في المباراة ، أي حوالي 100 مباراة. ليس لدينا مبرمج خادم ولا نحتاجه. يكتب العملاء كل المنطق في محرر الوحدة ، رايدر ، في C # ويعمل على خادم اللعبة. دائما تقريبا. قمنا بتقليل حجم الحزمة 17 مرة وخفضنا تخصيصات الذاكرة 80 مرة - حتى الآن أقل من كيلوبايت على العميل والخادم. كان متوسط ping 200-250 مللي ثانية ، والآن أصبح 150. 200 هو المعيار لألعاب شبكة الجوال ، على عكس جهاز الكمبيوتر ، حيث يحدث كل شيء بشكل أسرع ، خاصة على الشبكة المحلية.

نخطط لعزل ما هو مكتوب في إطار منفصل لاستخدامه في مشاريع أخرى. ولكن حتى الآن ، لا يوجد حديث عن المصدر المفتوح. وإضافة الاستيفاء هناك. الآن لدينا 30 نقطة في الثانية ، يمكننا الرسم كما هو. ولكن هناك ألعاب تكفي 20 قطعة في الثانية أو 10 ، وبناءً على ذلك ، إذا رسمنا 10 مرات في الثانية ، فإن الشخصيات سوف تتحرك في الهزات. لذلك ، هناك حاجة إلى الاستيفاء. كتبنا مكتبة الشبكة الخاصة بنا بدلاً من الفوتون - لا توجد تخصيصات للذاكرة هناك.
لا تزال هناك أجزاء لا يمكنك كتابتها بيديك ، ولكن إنشاء رمز. على سبيل المثال ، عندما نرسل حالة العالم إلى عميل ، نقطع البيانات التي لا يحتاجها. بينما نقوم بذلك بأيدينا وعندما تظهر ميزة جديدة ، وننسى قطع هذه البيانات ، حدث خطأ ما. في الواقع ، يمكن إنشاء ذلك عن طريق وضع علامة على بعض السمات.
أسئلة من الجمهور
- ما الذي تستخدمه لإنشاء التعليمات البرمجية؟ قرارك الخاص؟- كل شيء بسيط - اليدين. كنا نظن أن نصنع شيئًا ما جاهزًا ، ولكن اتضح أنه أسرع لمجرد الكتابة بأيدينا. , .
— , , . Unity #, . .NET Core, , . - ?— , , , , . , , , . . , , .
— ? , ?— , , , . 18-,19- 20- . 18-, 20-, 19- , — . , .
— , ?— 2D — , . : UDP, , : , . .
— ?"نعم بالطبع." - ( , , ), 2 : , .
— . ? ? 1000 , ? , ?— , . , -, , . , 30 .
— , ?— . , ( ), . — , , . - , , . , , , , . .
— ECS, , ? ?— 30 , . 80 , . .
— prediction. 20- - , , - — , ? , . - ?— : . (, 15-) 16-,17-,18- .
— ?— , . , , . Entity ( ), . — , . ID , .
— - — , , , ? , ?— , , . 3D , — , , - . , , . top-down, — . . , , , . .
— ?— . يحدث هذا أيضا.
— , , - . - . - , , , 500 , , - - . ?— .

, .. 20- 20- , . — , . : 20- , ? , . , — - . , . , « - , 21-, 18-». : «, - ». .
— .. , ?— , .
— reliable UDP — - ?— Photon, Photon reliable UDP, unreliable, c .
— ?— , -. , . , . , . , . 100%, , 80%, .
— ?— , , Photon , MTU.
— ? ?— , , , . . , . , , , .
— , , ?— , . , . , , . , - . , . , .
— / — - . , .— , . , ( ), -, , -. , . — , .
— , - . ?— , . : ECS, . , ECS . , ECS . , . , , , ( , , , , , ). 2D , , 3D — . 3D , , . . - , . , - -, .
— , ECS , . , , C#?— — .
— .. ES ? , ECS — , , , . .. ECS — , .— , , . , . — , , . , O - , , .
— , ECS- ?— -, ECS , , ( ) — , . , — . — , , . , , , ..
Pixonic DevGAMM Talks