इस अप्रैल में वॉर रोबोट्स अपनी 10वीं वर्षगांठ मना रहा है! और आज तक, हम इसे विकसित और समर्थन करना जारी रखते हैं, न केवल अपने खिलाड़ियों के लिए नई सुविधाएँ जारी करते हैं बल्कि तकनीकी रूप से भी इसमें सुधार करते हैं।
इस लेख में, हम इस बड़ी परियोजना के तकनीकी विकास में अपने कई वर्षों के अनुभव पर चर्चा करेंगे। लेकिन सबसे पहले, यहाँ परियोजना का एक स्नैपशॉट दिया गया है:
इस तरह की परियोजना की कार्यक्षमता को बनाए रखने और आगे उच्च-गुणवत्ता वाले विकास को सुनिश्चित करने के लिए, केवल तत्काल उत्पाद कार्यों पर काम करना पर्याप्त नहीं है; इसकी तकनीकी स्थिति में सुधार करना, विकास को सरल बनाना और प्रक्रियाओं को स्वचालित करना भी महत्वपूर्ण है - जिसमें नई सामग्री के निर्माण से संबंधित प्रक्रियाएं भी शामिल हैं। इसके अलावा, हमें उपलब्ध उपयोगकर्ता उपकरणों के बदलते बाजार के साथ लगातार तालमेल बिठाना चाहिए।
यह पाठ पिक्सोनिक (MY.GAMES) के विकास विभाग के प्रमुख पावेल ज़िनोव और वॉर रोबोट्स के प्रमुख डेवलपर दिमित्री चेतवेरिकोव के साक्षात्कार पर आधारित है।
आइए 2014 में वापस जाएं: वॉर रोबोट्स परियोजना को शुरू में एक छोटी सी टीम द्वारा बनाया गया था, और सभी तकनीकी समाधान तेजी से विकास और बाजार में नई सुविधाओं की डिलीवरी के प्रतिमान में फिट बैठते हैं। इस समय, कंपनी के पास समर्पित सर्वर होस्ट करने के लिए बड़े संसाधन नहीं थे, और इस प्रकार, वॉर रोबोट्स ने पी2पी लॉजिक पर आधारित नेटवर्क मल्टीप्लेयर के साथ बाजार में प्रवेश किया।
क्लाइंट के बीच डेटा ट्रांसफर करने के लिए फोटॉन क्लाउड का इस्तेमाल किया गया: प्रत्येक खिलाड़ी का आदेश, चाहे वह मूविंग हो, शूटिंग हो या कोई अन्य आदेश, अलग-अलग RPC का उपयोग करके फोटॉन क्लाउड सर्वर को भेजा जाता था। चूंकि कोई समर्पित सर्वर नहीं था, इसलिए गेम में एक मास्टर क्लाइंट था, जो सभी खिलाड़ियों के लिए मैच की स्थिति की विश्वसनीयता के लिए जिम्मेदार था। उसी समय, शेष खिलाड़ी अपने स्थानीय क्लाइंट पर पूरे गेम की स्थिति को पूरी तरह से संसाधित करते थे।
उदाहरण के लिए, मूवमेंट के लिए कोई सत्यापन नहीं था - स्थानीय क्लाइंट ने अपने रोबोट को अपनी इच्छानुसार स्थानांतरित किया, यह स्थिति मास्टर क्लाइंट को भेजी गई, और मास्टर क्लाइंट ने बिना किसी शर्त के इस स्थिति पर विश्वास किया और बस इसे मैच में अन्य क्लाइंट को भेज दिया। प्रत्येक क्लाइंट ने स्वतंत्र रूप से लड़ाई का एक लॉग रखा और मैच के अंत में इसे सर्वर को भेजा, फिर सर्वर ने सभी खिलाड़ियों के लॉग को संसाधित किया, एक इनाम दिया, और मैच के परिणाम सभी खिलाड़ियों को भेजे।
हमने प्लेयर प्रोफाइल के बारे में जानकारी संग्रहीत करने के लिए एक विशेष प्रोफ़ाइल सर्वर का उपयोग किया। इसमें कैसंड्रा डेटाबेस वाले कई सर्वर शामिल थे। प्रत्येक सर्वर टॉमकैट पर एक सरल ऐप सर्वर था, और क्लाइंट HTTP के माध्यम से इसके साथ बातचीत करते थे।
गेमप्ले में इस्तेमाल किए गए दृष्टिकोण में कई कमियाँ थीं। बेशक, टीम को इनके बारे में पता था, लेकिन विकास की गति और अंतिम उत्पाद को बाज़ार में पहुँचाने के कारण, कई समझौते करने पड़े।
इन नुकसानों में सबसे पहले, मास्टर क्लाइंट कनेक्शन की गुणवत्ता थी। अगर क्लाइंट का नेटवर्क खराब था, तो मैच में सभी खिलाड़ियों को लैग का सामना करना पड़ा। और, अगर मास्टर क्लाइंट बहुत शक्तिशाली स्मार्टफोन पर नहीं चल रहा था, तो उस पर रखे गए उच्च लोड के कारण, गेम में डेटा ट्रांसफर में भी देरी हुई। इसलिए, इस मामले में, मास्टर क्लाइंट के अलावा, अन्य खिलाड़ियों को भी नुकसान उठाना पड़ा।
दूसरी कमी यह थी कि इस आर्किटेक्चर में धोखेबाज़ों के साथ समस्याएँ होने की संभावना थी। चूँकि अंतिम स्थिति मास्टर क्लाइंट से स्थानांतरित की गई थी, इसलिए यह क्लाइंट अपने विवेक पर कई मैच पैरामीटर बदल सकता था, उदाहरण के लिए, मैच में कैप्चर किए गए ज़ोन की संख्या की गणना करना।
तीसरा, फोटोन क्लाउड पर मैचमेकिंग कार्यक्षमता के साथ एक समस्या मौजूद है: फोटोन क्लाउड मैचमेकिंग रूम में सबसे पुराना खिलाड़ी मास्टर क्लाइंट बन जाता है, और अगर मैचमेकिंग के दौरान उनके साथ कुछ होता है (उदाहरण के लिए, डिस्कनेक्शन), तो समूह निर्माण पर नकारात्मक प्रभाव पड़ता है। संबंधित मजेदार तथ्य: किसी समूह को मैच में भेजने के बाद फोटोन क्लाउड में मैचमेकिंग को बंद होने से रोकने के लिए, कुछ समय के लिए, हमने अपने कार्यालय में एक साधारण पीसी भी स्थापित किया, और यह हमेशा मैचमेकिंग का समर्थन करता था, जिसका अर्थ है कि फोटोन क्लाउड के साथ मैचमेकिंग विफल नहीं हो सकती थी।
एक समय ऐसा आया जब समस्याओं और समर्थन अनुरोधों की संख्या एक महत्वपूर्ण स्तर पर पहुंच गई, और हमने गेम की तकनीकी वास्तुकला को विकसित करने के बारे में गंभीरता से सोचना शुरू कर दिया - इस नई वास्तुकला को इन्फ्रास्ट्रक्चर 2.0 कहा गया।
इस आर्किटेक्चर के पीछे मुख्य विचार समर्पित गेम सर्वर का निर्माण था। उस समय, क्लाइंट की टीम में व्यापक सर्वर विकास अनुभव वाले प्रोग्रामर की कमी थी। हालाँकि, कंपनी एक साथ सर्वर-आधारित, उच्च-लोड एनालिटिक्स प्रोजेक्ट पर काम कर रही थी, जिसे हमने AppMetr कहा। टीम ने एक ऐसा उत्पाद बनाया था जो प्रतिदिन अरबों संदेशों को संसाधित करता था, और उनके पास सर्वर समाधानों के विकास, कॉन्फ़िगरेशन और सही आर्किटेक्चर में व्यापक विशेषज्ञता थी। और इसलिए, उस टीम के कुछ सदस्य इंफ्रास्ट्रक्चर 2.0 पर काम में शामिल हो गए।
2015 में, काफी कम समय में, विंडोज सर्वर पर चलने वाले फोटोन सर्वर SDK फ्रेमवर्क में लिपटे एक .NET सर्वर का निर्माण किया गया। हमने फोटोन क्लाउड को छोड़ने का फैसला किया, क्लाइंट प्रोजेक्ट में केवल फोटोन सर्वर SDK नेटवर्क फ्रेमवर्क को रखा और मैचमेकिंग के लिए क्लाइंट और संबंधित सर्वर को जोड़ने के लिए एक मास्टर सर्वर बनाया। कुछ तर्क क्लाइंट से एक समर्पित गेम सर्वर पर ले जाया गया। विशेष रूप से, बुनियादी क्षति सत्यापन शुरू किया गया था, साथ ही सर्वर पर मैच परिणाम गणना भी रखी गई थी।
इंफ्रास्ट्रक्चर 2.0 को सफलतापूर्वक बनाने के बाद, हमें एहसास हुआ कि हमें सेवाओं की ज़िम्मेदारियों को अलग करने की दिशा में आगे बढ़ना जारी रखना चाहिए: इसका नतीजा माइक्रोसर्विस आर्किटेक्चर का निर्माण था। इस आर्किटेक्चर पर बनाया गया पहला माइक्रोसर्विस क्लैन था।
वहां से, एक अलग संचार सेवा सामने आई, और यह माइक्रोसर्विस के बीच डेटा स्थानांतरित करने के लिए जिम्मेदार थी। क्लाइंट को गेम सर्वर पर मेटा मैकेनिक्स के लिए जिम्मेदार "हैंगर" के साथ कनेक्शन स्थापित करना और फोटॉन क्लाउड पर यूडीपी का उपयोग करके एपीआई अनुरोध (सेवाओं के साथ बातचीत करने के लिए एक एकल प्रवेश बिंदु) करना सिखाया गया था। धीरे-धीरे, सेवाओं की संख्या बढ़ी और, परिणामस्वरूप, हमने मैचमेकिंग माइक्रोसर्विस को फिर से तैयार किया। इसके साथ, समाचार कार्यक्षमता, इनबॉक्स, बनाया गया था।
जब हमने कबीले बनाए, तो यह स्पष्ट था कि खिलाड़ी खेल में एक-दूसरे से संवाद करना चाहते थे - उन्हें किसी तरह की चैट की ज़रूरत थी। यह मूल रूप से फोटॉन चैट के आधार पर बनाया गया था, लेकिन जैसे ही आखिरी क्लाइंट डिस्कनेक्ट हुआ, पूरा चैट इतिहास मिटा दिया गया। इसलिए, हमने इस समाधान को कैसंड्रा डेटाबेस पर आधारित एक अलग माइक्रोसर्विस में बदल दिया।
नए माइक्रोसर्विस आर्किटेक्चर ने हमें बड़ी संख्या में सेवाओं का प्रबंधन करने की सुविधा दी, जो एक-दूसरे से स्वतंत्र थीं, जिसका अर्थ था पूरे सिस्टम को क्षैतिज रूप से स्केल करना और डाउनटाइम से बचना।
हमारे गेम में, सर्वर को रोके बिना अपडेट हुए। सर्वर प्रोफ़ाइल क्लाइंट के कई संस्करणों के साथ संगत थी, और गेम सर्वर के लिए, हमारे पास क्लाइंट के पुराने और नए संस्करणों के लिए हमेशा सर्वरों का एक पूल होता है, यह पूल एप्लिकेशन स्टोर में नए संस्करण के रिलीज़ होने के बाद धीरे-धीरे बदल गया, और गेम सर्वर पुराने संस्करण से समय के साथ गायब हो गए। वर्तमान बुनियादी ढांचे की सामान्य रूपरेखा को इन्फ्रास्ट्रक्चर 4.0 कहा जाता था और यह इस तरह दिखता था:
आर्किटेक्चर को बदलने के अलावा, हमें इस बात को लेकर भी दुविधा का सामना करना पड़ा कि हमारे सर्वर कहाँ स्थित होने चाहिए क्योंकि उन्हें दुनिया भर के खिलाड़ियों को कवर करना था। शुरुआत में, कई माइक्रोसर्विस कई कारणों से Amazon AWS में स्थित थे, विशेष रूप से, स्केलिंग के मामले में इस सिस्टम द्वारा प्रदान की जाने वाली लचीलेपन के कारण, क्योंकि गेमिंग ट्रैफ़िक बढ़ने के समय यह बहुत महत्वपूर्ण था (जैसे कि जब इसे स्टोर में दिखाया गया था और UA को बढ़ावा देने के लिए)। इसके अतिरिक्त, उस समय, एशिया में एक अच्छा होस्टिंग प्रदाता ढूंढना मुश्किल था जो बाहरी दुनिया के साथ अच्छी नेटवर्क गुणवत्ता और कनेक्शन प्रदान कर सके।
Amazon AWS का एकमात्र नुकसान इसकी उच्च लागत थी। इसलिए, समय के साथ, हमारे कई सर्वर हमारे अपने हार्डवेयर पर चले गए - सर्वर जो हम दुनिया भर के डेटा केंद्रों में किराए पर लेते हैं। फिर भी, Amazon AWS आर्किटेक्चर का एक महत्वपूर्ण हिस्सा बना रहा, क्योंकि इसने लगातार बदलते कोड (विशेष रूप से, लीग, क्लैन, चैट और समाचार सेवाओं के लिए कोड) के विकास की अनुमति दी और जो स्थिरता परीक्षणों द्वारा पर्याप्त रूप से कवर नहीं किया गया था। लेकिन, जैसे ही हमें एहसास हुआ कि माइक्रोसर्विस स्थिर है, हमने इसे अपनी सुविधाओं में स्थानांतरित कर दिया। वर्तमान में, हमारी सभी माइक्रोसर्विस हमारे हार्डवेयर सर्वर पर चलती हैं।
2016 में, गेम के रेंडरिंग में महत्वपूर्ण बदलाव किए गए: लड़ाई में सभी मेच के लिए एकल बनावट एटलस के साथ उबरशैडर्स की अवधारणा दिखाई दी, जिसने ड्रॉ कॉल की संख्या को बहुत कम कर दिया और गेम प्रदर्शन में सुधार किया।
यह स्पष्ट हो गया कि हमारा गेम हजारों अलग-अलग डिवाइस पर खेला जा रहा था, और हम प्रत्येक खिलाड़ी को सर्वोत्तम संभव गेमिंग परिस्थितियाँ प्रदान करना चाहते थे। इसलिए, हमने क्वालिटी मैनेजर बनाया, जो मूल रूप से एक फ़ाइल है जो खिलाड़ी के डिवाइस का विश्लेषण करती है और कुछ गेम या रेंडरिंग सुविधाओं को सक्षम (या अक्षम) करती है। इसके अलावा, इस सुविधा ने हमें इन कार्यों को विशिष्ट डिवाइस मॉडल तक प्रबंधित करने की अनुमति दी ताकि हम अपने खिलाड़ियों द्वारा अनुभव की जा रही समस्याओं को जल्दी से ठीक कर सकें।
सर्वर से क्वालिटी मैनेजर सेटिंग्स डाउनलोड करना और वर्तमान प्रदर्शन के आधार पर डिवाइस पर गुणवत्ता का गतिशील रूप से चयन करना भी संभव है। तर्क काफी सरल है: क्वालिटी मैनेजर का पूरा शरीर ब्लॉकों में विभाजित है, जिनमें से प्रत्येक प्रदर्शन के किसी न किसी पहलू के लिए जिम्मेदार है। (उदाहरण के लिए, छाया या एंटी-अलियासिंग की गुणवत्ता।) यदि किसी उपयोगकर्ता का प्रदर्शन प्रभावित होता है, तो सिस्टम ब्लॉक के अंदर के मानों को बदलने और एक विकल्प चुनने का प्रयास करता है जिससे प्रदर्शन में वृद्धि होगी। हम थोड़ी देर बाद क्वालिटी मैनेजर के विकास पर लौटेंगे, लेकिन इस स्तर पर, इसका कार्यान्वयन काफी तेज़ था और नियंत्रण का आवश्यक स्तर प्रदान करता था।
ग्राफ़िक्स विकास जारी रहने के कारण क्वालिटी मैनेजर पर भी काम करना ज़रूरी था। गेम में अब कैस्केडिंग डायनेमिक शैडोज़ हैं, जिन्हें पूरी तरह से हमारे ग्राफ़िक्स प्रोग्रामर्स द्वारा लागू किया गया है।
धीरे-धीरे, परियोजना के कोड में बहुत सारी इकाइयाँ दिखाई दीं, इसलिए हमने तय किया कि उनके जीवनकाल का प्रबंधन करना शुरू करना अच्छा होगा, साथ ही विभिन्न कार्यक्षमता तक पहुँच को सीमित करना भी। यह हैंगर और कॉम्बैट कोड को अलग करने के लिए विशेष रूप से महत्वपूर्ण था क्योंकि गेम संदर्भ बदलने पर कई संसाधन साफ़ नहीं हो रहे थे। हमने विभिन्न IoC निर्भरता प्रबंधन कंटेनरों की खोज शुरू की। विशेष रूप से, हमने StrangeIoC समाधान को देखा। उस समय, समाधान हमें बोझिल लगा, और इसलिए हमने परियोजना में अपना स्वयं का सरल DI लागू किया। हमने हैंगर और युद्ध संदर्भ भी पेश किए।
इसके अलावा, हमने परियोजना के गुणवत्ता नियंत्रण पर काम करना शुरू कर दिया; उत्पादन वातावरण में क्रैश, एएनआर और अपवादों की पहचान करने के लिए फायरबेस क्रैशलिटिक्स को गेम में एकीकृत किया गया।
AppMetr नामक हमारे आंतरिक विश्लेषणात्मक समाधान का उपयोग करके, हमने ग्राहक की स्थिति की नियमित निगरानी और रिलीज़ के दौरान किए गए परिवर्तनों की तुलना के लिए आवश्यक डैशबोर्ड बनाए। इसके अलावा, परियोजना की गुणवत्ता में सुधार करने और कोड में किए गए परिवर्तनों में विश्वास बढ़ाने के लिए, हमने ऑटोटेस्ट पर शोध करना शुरू किया।
सामग्री में संपत्तियों और अद्वितीय बगों की संख्या में वृद्धि ने हमें संपत्तियों को व्यवस्थित करने और एकीकृत करने के बारे में सोचने पर मजबूर कर दिया। यह विशेष रूप से मेच के लिए सच था क्योंकि उनका निर्माण उनमें से प्रत्येक के लिए अद्वितीय था; इसके लिए, हमने यूनिटी में उपकरण बनाए, और इनके साथ, हमने मुख्य आवश्यक घटकों के साथ मेच डमी बनाए। इसका मतलब था कि गेम डिज़ाइन विभाग उन्हें आसानी से संपादित कर सकता था - और इस तरह हमने पहली बार मेच के साथ अपने काम को एकीकृत करना शुरू किया।
प्रोजेक्ट लगातार आगे बढ़ता रहा और टीम ने इसे दूसरे प्लैटफ़ॉर्म पर रिलीज़ करने के बारे में सोचना शुरू कर दिया। साथ ही, एक और बात यह है कि उस समय कुछ मोबाइल प्लैटफ़ॉर्म के लिए यह ज़रूरी था कि गेम प्लैटफ़ॉर्म के ज़्यादा से ज़्यादा नेटिव फ़ंक्शन को सपोर्ट करे, क्योंकि इससे गेम को फ़ीचर किया जा सकता था। इसलिए, हमने Apple TV के लिए War Robots के एक प्रायोगिक संस्करण और Apple Watch के लिए एक साथी ऐप पर काम करना शुरू किया।
इसके अतिरिक्त, 2016 में, हमने गेम को एक ऐसे प्लेटफ़ॉर्म पर लॉन्च किया जो हमारे लिए नया था - Amazon AppStore। तकनीकी विशेषताओं के संदर्भ में, यह प्लेटफ़ॉर्म अद्वितीय है क्योंकि इसमें Apple की तरह उपकरणों की एक एकीकृत लाइन है, लेकिन इस लाइन की शक्ति कम-अंत वाले Android के स्तर पर है। इसे ध्यान में रखते हुए, इस प्लेटफ़ॉर्म पर लॉन्च करते समय, मेमोरी उपयोग और प्रदर्शन को अनुकूलित करने के लिए महत्वपूर्ण काम किया गया था, उदाहरण के लिए, हमने एटलस, टेक्सचर कम्प्रेशन के साथ काम किया। लॉगिन और उपलब्धियों के लिए गेम सेंटर के एक एनालॉग, Amazon भुगतान प्रणाली को क्लाइंट में एकीकृत किया गया था, और इसलिए खिलाड़ी के लॉगिन के साथ काम करने का प्रवाह फिर से तैयार किया गया था, और पहली उपलब्धियाँ लॉन्च की गई थीं।
यह भी ध्यान देने योग्य है कि, साथ ही, क्लाइंट टीम ने पहली बार यूनिटी एडिटर के लिए उपकरणों का एक सेट विकसित किया, और इनसे इंजन में इन-गेम वीडियो शूट करना संभव हो गया। इससे हमारे मार्केटिंग विभाग के लिए संपत्तियों के साथ काम करना, युद्ध को नियंत्रित करना और कैमरे का उपयोग करके ऐसे वीडियो बनाना आसान हो गया, जिन्हें हमारे दर्शकों ने बहुत पसंद किया।
यूनिटी की अनुपस्थिति और विशेष रूप से सर्वर पर भौतिकी इंजन के कारण, अधिकांश मैच खिलाड़ी उपकरणों पर अनुकरण किए जाते रहे। इस वजह से, धोखेबाजों के साथ समस्याएँ बनी रहीं। समय-समय पर, हमारी सहायता टीम को धोखेबाजों के वीडियो के साथ हमारे उपयोगकर्ताओं से प्रतिक्रिया मिली: उन्होंने सुविधाजनक समय पर गति बढ़ा दी, नक्शे के चारों ओर उड़ गए, एक कोने से अन्य खिलाड़ियों को मार डाला, अमर हो गए, और इसी तरह।
आदर्श रूप से, हम सभी मैकेनिक्स को सर्वर पर स्थानांतरित कर देंगे; हालाँकि, इस तथ्य के अलावा कि खेल निरंतर विकास में था और पहले से ही काफी मात्रा में विरासत कोड जमा हो चुका था, एक आधिकारिक सर्वर के साथ एक दृष्टिकोण में अन्य नुकसान भी हो सकते हैं। उदाहरण के लिए, बुनियादी ढांचे पर लोड बढ़ाना और बेहतर इंटरनेट कनेक्शन की मांग करना। यह देखते हुए कि हमारे अधिकांश उपयोगकर्ता 3G/4G नेटवर्क पर खेलते हैं, यह दृष्टिकोण, हालांकि स्पष्ट है, समस्या का प्रभावी समाधान नहीं था। टीम के भीतर धोखेबाजों का मुकाबला करने के वैकल्पिक दृष्टिकोण के रूप में, हम एक नए विचार के साथ आए - एक "कोरम" बनाना।
कोरम एक ऐसा तंत्र है जो आपको नुकसान की पुष्टि करते समय विभिन्न खिलाड़ियों के कई सिमुलेशन की तुलना करने की अनुमति देता है; नुकसान उठाना खेल की मुख्य विशेषताओं में से एक है, जिस पर वस्तुतः इसकी बाकी स्थिति निर्भर करती है। उदाहरण के लिए, यदि आप अपने विरोधियों को नष्ट कर देते हैं, तो वे बीकन पर कब्जा नहीं कर पाएंगे।
इस निर्णय का विचार इस प्रकार था: प्रत्येक खिलाड़ी अभी भी पूरी दुनिया का अनुकरण कर रहा था (अन्य खिलाड़ियों को गोली मारने सहित) और परिणाम सर्वर को भेज रहा था। सर्वर ने सभी खिलाड़ियों के परिणामों का विश्लेषण किया और यह निर्णय लिया कि क्या खिलाड़ी को अंततः नुकसान हुआ है और किस हद तक। हमारे मैचों में 12 लोग शामिल हैं, इसलिए सर्वर के लिए यह विचार करने के लिए कि नुकसान हुआ है, यह तथ्य 7 खिलाड़ियों के स्थानीय सिमुलेशन के भीतर दर्ज होना पर्याप्त है। फिर ये परिणाम आगे की पुष्टि के लिए सर्वर को भेजे जाएंगे। योजनाबद्ध रूप से, इस एल्गोरिथ्म को निम्नानुसार दर्शाया जा सकता है:
इस योजना से हम उन धोखेबाजों की संख्या को काफी हद तक कम करने में सफल रहे, जो युद्ध में खुद को अजेय बना लेते थे। निम्नलिखित ग्राफ इन उपयोगकर्ताओं के खिलाफ शिकायतों की संख्या के साथ-साथ सर्वर पर क्षति गणना सुविधाओं को सक्षम करने और क्षति कोरम को सक्षम करने के चरणों को दर्शाता है:
इस क्षति-निपटान तंत्र ने धोखाधड़ी की समस्याओं को लंबे समय तक हल कर दिया, क्योंकि सर्वर पर भौतिकी की कमी के बावजूद (और इसलिए सतह की स्थलाकृति और अंतरिक्ष में रोबोट की वास्तविक स्थिति जैसी चीजों को ध्यान में रखने में असमर्थता), सभी ग्राहकों के लिए सिमुलेशन के परिणाम और उनकी आम सहमति से यह स्पष्ट समझ मिलती थी कि किसने किसको और किन परिस्थितियों में नुकसान पहुंचाया।
समय के साथ, डायनेमिक शैडो के अलावा, हमने यूनिटी पोस्ट प्रोसेसिंग स्टैक और बैच रेंडरिंग का उपयोग करके गेम में पोस्ट-इफेक्ट्स जोड़े। पोस्ट-प्रोसेसिंग इफ़ेक्ट्स लागू करने के परिणामस्वरूप बेहतर ग्राफ़िक्स के उदाहरण नीचे दी गई तस्वीर में देखे जा सकते हैं:
डीबग बिल्ड में क्या हो रहा था, इसे बेहतर ढंग से समझने के लिए, हमने एक लॉगिंग सिस्टम बनाया और आंतरिक बुनियादी ढांचे में एक स्थानीय सेवा तैनात की जो आंतरिक परीक्षकों से लॉग एकत्र कर सकती थी और बग के कारणों का पता लगाना आसान बना सकती थी। यह उपकरण अभी भी QA द्वारा प्लेटेस्ट के लिए उपयोग किया जाता है, और इसके काम के परिणाम Jira में टिकटों से जुड़े होते हैं।
हमने प्रोजेक्ट में एक स्व-लिखित पैकेज मैनेजर भी जोड़ा। शुरू में, हम विभिन्न पैकेज और बाहरी प्लगइन्स (जिनमें से प्रोजेक्ट में पहले से ही पर्याप्त संख्या में प्लगइन्स थे) के साथ काम को बेहतर बनाना चाहते थे। हालाँकि, उस समय यूनिटी की कार्यक्षमता पर्याप्त नहीं थी, इसलिए हमारी आंतरिक प्लेटफ़ॉर्म टीम ने पैकेज वर्जनिंग, NPM का उपयोग करके स्टोरेज और GitHub पर लिंक जोड़कर पैकेज को प्रोजेक्ट से जोड़ने की क्षमता के साथ अपना स्वयं का समाधान विकसित किया। चूँकि हम अभी भी एक मूल इंजन समाधान का उपयोग करना चाहते थे, इसलिए हमने यूनिटी के सहकर्मियों से परामर्श किया और हमारे कई विचारों को यूनिटी के अंतिम समाधान में शामिल किया गया जब उन्होंने 2018 में अपना पैकेज मैनेजर जारी किया।
हमने उन प्लेटफ़ॉर्म की संख्या का विस्तार करना जारी रखा जहाँ हमारा गेम उपलब्ध था। आखिरकार, Facebook Gameroom, एक ऐसा प्लेटफ़ॉर्म जो कीबोर्ड और माउस को सपोर्ट करता है, सामने आया। यह Facebook (मेटा) का एक समाधान है, जो उपयोगकर्ताओं को PC पर एप्लिकेशन चलाने की अनुमति देता है; अनिवार्य रूप से, यह स्टीम स्टोर का एनालॉग है। बेशक, Facebook के दर्शक काफी विविध हैं, और Facebook Gameroom को बड़ी संख्या में डिवाइस पर लॉन्च किया गया था, मुख्य रूप से गैर-गेमिंग वाले। इसलिए, हमने गेम में मोबाइल ग्राफ़िक्स रखने का फैसला किया ताकि मुख्य दर्शकों के PC पर बोझ न पड़े। तकनीकी दृष्टिकोण से, गेम में केवल महत्वपूर्ण बदलाव SDK, भुगतान प्रणाली और मूल यूनिटी इनपुट सिस्टम का उपयोग करके कीबोर्ड और माउस के लिए समर्थन का एकीकरण था।
तकनीकी रूप से, यह स्टीम के लिए गेम के निर्माण से थोड़ा अलग था, लेकिन उपकरणों की गुणवत्ता काफी कम थी क्योंकि प्लेटफ़ॉर्म को काफी सरल उपकरणों वाले आकस्मिक खिलाड़ियों के लिए एक जगह के रूप में तैनात किया गया था जो ब्राउज़र से ज़्यादा कुछ नहीं चला सकते थे, इस बात को ध्यान में रखते हुए फेसबुक को काफी बड़े बाजार में प्रवेश करने की उम्मीद थी। इन उपकरणों के संसाधन सीमित थे, और विशेष रूप से प्लेटफ़ॉर्म में लगातार मेमोरी और प्रदर्शन संबंधी समस्याएं थीं।
बाद में, प्लेटफ़ॉर्म बंद हो गया, और हमने अपने खिलाड़ियों को स्टीम पर स्थानांतरित कर दिया, जहाँ यह संभव था। इसके लिए, हमने प्लेटफ़ॉर्म के बीच खातों को स्थानांतरित करने के लिए कोड के साथ एक विशेष प्रणाली विकसित की।
2017 की एक और उल्लेखनीय घटना: iPhone X की रिलीज़, नॉच वाला पहला स्मार्टफोन। उस समय, यूनिटी नॉच वाले डिवाइस का समर्थन नहीं करती थी, इसलिए हमें UnityEngine.Screen.safeArea मापदंडों के आधार पर एक कस्टम समाधान बनाना पड़ा, जो UI को फ़ोन स्क्रीन पर अलग-अलग सुरक्षित क्षेत्रों को स्केल करने और उनसे बचने के लिए मजबूर करता है।
इसके अलावा, 2017 में, हमने कुछ और करने का फैसला किया - स्टीम पर हमारे गेम का VR संस्करण जारी करना। विकास लगभग छह महीने तक चला और उस समय उपलब्ध सभी हेलमेटों पर परीक्षण शामिल था: ओकुलस, एचटीसी विवे और विंडोज मिक्स्ड रियलिटी। यह काम ओकुलस एपीआई और स्टीम एपीआई का उपयोग करके किया गया था। इसके अलावा, PS VR हेडसेट के लिए एक डेमो संस्करण तैयार किया गया था, साथ ही MacOS के लिए समर्थन भी।
तकनीकी दृष्टिकोण से, स्थिर FPS बनाए रखना आवश्यक था: PS VR के लिए 60 FPS और HTC Vive के लिए 90 FPS। इसे प्राप्त करने के लिए, मानक फ्रस्टम और ऑक्लूज़न के अलावा, स्व-स्क्रिप्टेड ज़ोन कलिंग का उपयोग किया गया, साथ ही रीप्रोजेक्शन (जब कुछ फ़्रेम पिछले फ़्रेम के आधार पर उत्पन्न होते हैं)।
मोशन सिकनेस की समस्या को हल करने के लिए, एक दिलचस्प रचनात्मक और तकनीकी समाधान अपनाया गया: हमारा खिलाड़ी एक रोबोट पायलट बन गया और कॉकपिट में बैठ गया। केबिन एक स्थिर तत्व था, इसलिए मस्तिष्क ने इसे दुनिया में किसी तरह के स्थिर के रूप में माना, और इसलिए, अंतरिक्ष में आंदोलन बहुत अच्छी तरह से काम करता था।
गेम में एक ऐसा परिदृश्य भी था जिसके लिए कई अलग-अलग ट्रिगर्स, स्क्रिप्ट और होममेड टाइमलाइन के विकास की आवश्यकता थी क्योंकि यूनिटी के उस संस्करण में सिनेमशीन अभी तक उपलब्ध नहीं था।
प्रत्येक हथियार के लिए लक्ष्यीकरण, लॉकिंग, ट्रैकिंग और स्वचालित लक्ष्यीकरण का तर्क शुरू से ही लिखा गया था।
संस्करण स्टीम पर जारी किया गया था और हमारे खिलाड़ियों द्वारा अच्छी तरह से प्राप्त किया गया था। हालांकि, किकस्टार्टर अभियान के बाद, हमने परियोजना के विकास को जारी नहीं रखने का फैसला किया क्योंकि वीआर के लिए एक पूर्ण-विकसित पीवीपी शूटर का विकास तकनीकी जोखिमों और इस तरह की परियोजना के लिए बाजार की अनिच्छा से भरा था।
जब हम खेल के तकनीकी घटक को बेहतर बनाने, साथ ही नए बनाने और मौजूदा मैकेनिक्स और प्लेटफ़ॉर्म विकसित करने पर काम कर रहे थे, तो हमें खेल में पहली गंभीर बग का सामना करना पड़ा, जिसने नए प्रचार को लॉन्च करते समय राजस्व को नकारात्मक रूप से प्रभावित किया। समस्या यह थी कि "मूल्य" बटन को गलत तरीके से "पुरस्कार" के रूप में स्थानीयकृत किया गया था। अधिकांश खिलाड़ी इससे भ्रमित हो गए, उन्होंने असली मुद्रा के साथ खरीदारी की, और फिर रिफंड के लिए कहा।
तकनीकी समस्या यह थी कि, उस समय, हमारे सभी स्थानीयकरण गेम क्लाइंट में बनाए गए थे। जब यह समस्या सामने आई, तो हमने समझा कि हम अब ऐसे समाधान पर काम करना स्थगित नहीं कर सकते जो हमें स्थानीयकरण को अपडेट करने की अनुमति देता है। इस तरह CDN और साथ में मौजूद उपकरणों, जैसे कि TeamCity में प्रोजेक्ट, जो CDN पर स्थानीयकरण फ़ाइलों को अपलोड करने को स्वचालित करता है, पर आधारित एक समाधान बनाया गया।
इससे हमें हमारे द्वारा उपयोग की जाने वाली सेवाओं (POEditor) से स्थानीयकरण डाउनलोड करने और CDN पर कच्चा डेटा अपलोड करने की सुविधा मिली।
उसके बाद, सर्वर प्रोफ़ाइल ने स्थानीयकरण डेटा के अनुरूप क्लाइंट के प्रत्येक संस्करण के लिए लिंक सेट करना शुरू कर दिया। जब एप्लिकेशन लॉन्च किया गया, तो प्रोफ़ाइल सर्वर ने क्लाइंट को यह लिंक भेजना शुरू कर दिया, और यह डेटा डाउनलोड और कैश किया गया।
2018 में आगे बढ़ते हुए। जैसे-जैसे प्रोजेक्ट बढ़ता गया, सर्वर से क्लाइंट तक डेटा ट्रांसफर की मात्रा भी बढ़ती गई। सर्वर से कनेक्ट करते समय, बैलेंस, मौजूदा सेटिंग आदि के बारे में काफी डेटा डाउनलोड करना ज़रूरी था।
वर्तमान डेटा को XML प्रारूप में प्रस्तुत किया गया तथा मानक यूनिटी सीरिएलाइज़र द्वारा क्रमबद्ध किया गया।
क्लाइंट को लॉन्च करते समय, साथ ही प्रोफाइल सर्वर और गेम सर्वर के साथ संचार करते समय, काफी बड़ी मात्रा में डेटा स्थानांतरित करने के अलावा, प्लेयर डिवाइस ने वर्तमान शेष राशि को संग्रहीत करने और इसे क्रमबद्ध/विक्रमबद्ध करने में बहुत अधिक मेमोरी खर्च की।
यह स्पष्ट हो गया कि एप्लिकेशन के प्रदर्शन और स्टार्टअप समय को बेहतर बनाने के लिए वैकल्पिक प्रोटोकॉल खोजने के लिए अनुसंधान एवं विकास करना आवश्यक होगा।
हमारे परीक्षण डेटा पर अध्ययन के परिणाम इस तालिका में प्रदर्शित हैं:
शिष्टाचार | आकार | आवंटन | समय |
---|---|---|---|
एक्सएमएल | 2.2 एमबी | 18.4 एमबी | 518.4 एमएस |
मैसेजपैक (अनुबंध रहित) | 1.7 एमबी | 2 एमबी | 32.35 एमएस |
मैसेजपैक (स्ट्र कुंजियाँ) | 1.2 एमबी | 1.9 एमबी | 25.8 एमएस |
संदेश पैक (int कुंजियाँ) | 0.53 एमबी | 1.9 | 16.5 |
फ्लैटबफ़र्स | 0.5 एमबी | 216 बी | 0 एमएस / 12 एमएस / 450 केबी |
परिणामस्वरूप, हमने मैसेजपैक प्रारूप को चुना क्योंकि समान आउटपुट परिणामों के साथ फ्लैटबफर पर स्विच करने की तुलना में माइग्रेशन सस्ता था, खासकर जब मैसेजपैक का उपयोग पूर्णांक कुंजियों के साथ किया जाता है।
फ्लैटबफ़र्स (और प्रोटोकॉल बफ़र्स के साथ) के लिए संदेश प्रारूप को एक अलग भाषा में वर्णित करना, C# और जावा कोड उत्पन्न करना और एप्लिकेशन में उत्पन्न कोड का उपयोग करना आवश्यक है। चूँकि हम क्लाइंट और सर्वर को रीफैक्टर करने की इस अतिरिक्त लागत को उठाना नहीं चाहते थे, इसलिए हमने मैसेजपैक पर स्विच किया।
संक्रमण लगभग सहज था, और पहले रिलीज़ में, हमने XML पर वापस जाने की क्षमता का समर्थन किया जब तक कि हम आश्वस्त नहीं हो गए कि नई प्रणाली में कोई समस्या नहीं है। नए समाधान ने हमारे सभी कार्यों को कवर किया - इसने क्लाइंट लोडिंग समय को काफी कम कर दिया और सर्वर से अनुरोध करते समय प्रदर्शन में भी सुधार किया।
हमारे प्रोजेक्ट में प्रत्येक सुविधा या नया तकनीकी समाधान एक "फ़्लैग" के तहत जारी किया जाता है। यह फ़्लैग खिलाड़ी की प्रोफ़ाइल में संग्रहीत होता है और गेम शुरू होने पर क्लाइंट के पास बैलेंस के साथ आता है। एक नियम के रूप में, जब कोई नई कार्यक्षमता जारी की जाती है, विशेष रूप से तकनीकी, तो कई क्लाइंट रिलीज़ में दोनों कार्यक्षमताएँ होती हैं - पुरानी और नई। नई कार्यक्षमता सक्रियण ऊपर वर्णित फ़्लैग की स्थिति के अनुसार सख्ती से होता है, जो हमें वास्तविक समय में किसी विशेष समाधान की तकनीकी सफलता की निगरानी और समायोजन करने की अनुमति देता है।
धीरे-धीरे, प्रोजेक्ट में निर्भरता इंजेक्शन कार्यक्षमता को अपडेट करने का समय आ गया। वर्तमान वाला अब बड़ी संख्या में निर्भरताओं को संभाल नहीं सकता था और, कुछ मामलों में, गैर-स्पष्ट कनेक्शन पेश करता था जिन्हें तोड़ना और फिर से तैयार करना बहुत मुश्किल था। (यह एक या दूसरे तरीके से UI से संबंधित नवाचारों के लिए विशेष रूप से सच था।)
नया समाधान चुनते समय, चुनाव सरल था: प्रसिद्ध ज़ेनजेक्ट, जो हमारे अन्य प्रोजेक्ट में सिद्ध हो चुका था। यह प्रोजेक्ट लंबे समय से विकास में है, सक्रिय रूप से समर्थित है, नई सुविधाएँ जोड़ी जा रही हैं, और टीम के कई डेवलपर्स किसी न किसी तरह से इससे परिचित थे।
धीरे-धीरे, हमने Zenject का उपयोग करके वॉर रोबोट को फिर से लिखना शुरू किया। सभी नए मॉड्यूल इसके साथ विकसित किए गए थे, और पुराने को धीरे-धीरे रिफैक्टोर किया गया था। Zenject का उपयोग करने के बाद से, हमें उन संदर्भों के भीतर लोडिंग सेवाओं का एक स्पष्ट क्रम प्राप्त हुआ है, जिनकी हमने पहले चर्चा की थी (लड़ाई और हैंगर), और इसने डेवलपर्स को परियोजना के विकास में अधिक आसानी से गोता लगाने की अनुमति दी, साथ ही इन संदर्भों के भीतर अधिक आत्मविश्वास से नई सुविधाएँ विकसित कीं।
यूनिटी के अपेक्षाकृत नए संस्करणों में, एसिंक्रोनस कोड के साथ async/await के माध्यम से काम करना संभव हो गया। हमारे कोड में पहले से ही एसिंक्रोनस कोड का उपयोग किया गया था, लेकिन कोडबेस में कोई एकल मानक नहीं था, और चूंकि यूनिटी स्क्रिप्टिंग बैकएंड ने async/await का समर्थन करना शुरू कर दिया था, इसलिए हमने अनुसंधान और विकास करने और एसिंक्रोनस कोड के लिए अपने दृष्टिकोण को मानकीकृत करने का निर्णय लिया।
एक अन्य प्रेरणा कोड से कॉलबैक नरक को हटाना था - यह तब होता है जब अतुल्यकालिक कॉल की अनुक्रमिक श्रृंखला होती है, और प्रत्येक कॉल अगले के परिणामों की प्रतीक्षा करता है।
उस समय, कई लोकप्रिय समाधान थे, जैसे RSG या UniRx; हमने उन सभी की तुलना की और उन्हें एक एकल तालिका में संकलित किया:
| आरएसजी.प्रॉमिस | टीपीएल | टीपीएल w/प्रतीक्षा | यूनिटास्क | यूनिटास्क w/async |
---|---|---|---|---|---|
समाप्त होने तक का समय, s | 0.15843 | 0.1305305 | 0.1165172 | 0.1330536 | 0,1208553 |
पहला फ़्रेम समय/स्वयं, मि.से. | 105.25/82.63 | 13.51/11.86 | 21.89/18.40 | 28.80/24.89 | 19.27/15.94 |
प्रथम फ्रेम आवंटन | 40.8 एमबी | 2.1 एमबी | 5.0 एमबी | 8.5 एमबी | 5.4 एमबी |
दूसरा फ़्रेम समय/स्वयं, एमएस | 55.39/23.48 | 0.38/0.04 | 0.28/0.02 | 0.32/0.03 | 0.69/0.01 |
दूसरा फ्रेम आवंटन | 3.1 एमबी | 10.2 केबी | 10.3 केबी | 10.3 केबी | 10.4 केबी |
अंततः, हमने एसिंक्रोनस C# कोड के साथ काम करने के लिए मानक के रूप में नेटिव async/await का उपयोग करने का निर्णय लिया, जिससे अधिकांश डेवलपर्स परिचित हैं। हमने UniRx.Async का उपयोग न करने का निर्णय लिया, क्योंकि प्लगइन के लाभों में किसी तृतीय-पक्ष समाधान पर निर्भर रहने की आवश्यकता शामिल नहीं थी।
हमने न्यूनतम आवश्यक कार्यक्षमता के मार्ग का अनुसरण करना चुना। हमने RSG.Promise या धारकों का उपयोग छोड़ दिया, क्योंकि, सबसे पहले, नए डेवलपर्स को इन, आमतौर पर अपरिचित उपकरणों के साथ काम करने के लिए प्रशिक्षित करना आवश्यक था, और दूसरा, RSG.Promise या धारकों में async कार्यों का उपयोग करने वाले तृतीय-पक्ष कोड के लिए एक आवरण बनाना आवश्यक था। async/await के विकल्प ने कंपनी की परियोजनाओं के बीच विकास दृष्टिकोण को मानकीकृत करने में भी मदद की। इस परिवर्तन ने हमारी समस्याओं को हल कर दिया - हम एसिंक्रोनस कोड के साथ काम करने के लिए एक स्पष्ट प्रक्रिया के साथ समाप्त हुए और परियोजना से मुश्किल-से-समर्थित कॉलबैक नरक को हटा दिया।
UI में धीरे-धीरे सुधार किया गया। चूंकि हमारी टीम में, नई सुविधाओं की कार्यक्षमता क्लाइंट प्रोग्रामर द्वारा विकसित की जाती है, और लेआउट और इंटरफ़ेस विकास UI/UX विभाग द्वारा किया जाता है, इसलिए हमें एक ऐसे समाधान की आवश्यकता थी जो हमें एक ही सुविधा पर समानांतर काम करने की अनुमति दे - ताकि लेआउट डिज़ाइनर इंटरफ़ेस बना सके और उसका परीक्षण कर सके जबकि प्रोग्रामर तर्क लिखता है।
इस समस्या का समाधान इंटरफ़ेस के साथ काम करने के MVVM मॉडल में संक्रमण में पाया गया। यह मॉडल इंटरफ़ेस डिज़ाइनर को न केवल प्रोग्रामर को शामिल किए बिना इंटरफ़ेस डिज़ाइन करने की अनुमति देता है, बल्कि यह भी देखने की अनुमति देता है कि जब कोई वास्तविक डेटा अभी तक कनेक्ट नहीं हुआ है तो इंटरफ़ेस कुछ डेटा पर कैसे प्रतिक्रिया करेगा। ऑफ-द-शेल्फ समाधानों पर कुछ शोध के बाद, साथ ही पिक्सोनिक रिएक्टिवबाइंडिंग नामक हमारे अपने समाधान के त्वरित प्रोटोटाइप के बाद, हमने निम्नलिखित परिणामों के साथ एक तुलना तालिका संकलित की:
| सीपीयू समय | मेम. आवंटन | मेम. उपयोग |
---|---|---|---|
पेपरमिंट डेटा बाइंडिंग | 367 मि.से. | 73 केबी | 17.5 एमबी |
डिस्प्लेफैब | 223 मि.से. | 147 केबी | 8.5 एमबी |
यूनिटी वेल्ड | 267 मि.से. | 90 केबी | 15.5 एमबी |
पिक्सोनिक रिएक्टिवबाइंडिंग्स | 152 मि.से. | 23 केबी | 3 एमबी |
जैसे ही नई प्रणाली ने स्वयं को सिद्ध कर लिया, मुख्यतः नए इंटरफेस के उत्पादन को सरल बनाने के संदर्भ में, हमने इसका उपयोग सभी नई परियोजनाओं के लिए, साथ ही परियोजना में आने वाली सभी नई सुविधाओं के लिए करना शुरू कर दिया।
2019 तक, Apple और Samsung के कई डिवाइस रिलीज़ हो चुके थे जो ग्राफ़िक्स के मामले में काफ़ी दमदार थे, इसलिए हमारी कंपनी ने War Robots को बेहतर बनाने का विचार बनाया। हम इन सभी नए डिवाइस की शक्ति का फ़ायदा उठाना चाहते थे और गेम की विज़ुअल इमेज को अपडेट करना चाहते थे।
अद्यतन छवि के अतिरिक्त, हमारे अद्यतन उत्पाद के लिए हमारी कई आवश्यकताएं भी थीं: हम 60 एफपीएस गेम मोड का समर्थन करना चाहते थे, साथ ही विभिन्न उपकरणों के लिए संसाधनों की विभिन्न गुणवत्ता भी चाहते थे।
वर्तमान गुणवत्ता प्रबंधक को भी पुनः कार्य करने की आवश्यकता थी, क्योंकि ब्लॉकों के भीतर गुणवत्ताओं की संख्या बढ़ती जा रही थी, जिन्हें तत्काल बदल दिया जाता था, जिससे उत्पादकता कम हो जाती थी, साथ ही बड़ी संख्या में क्रमपरिवर्तन उत्पन्न हो जाते थे, जिनमें से प्रत्येक का परीक्षण करना पड़ता था, जिससे प्रत्येक रिलीज के साथ QA टीम पर अतिरिक्त लागत आती थी।
क्लाइंट पर फिर से काम करते समय हमने सबसे पहले शूटिंग को फिर से शुरू किया। मूल कार्यान्वयन फ्रेम रेंडरिंग गति पर निर्भर था क्योंकि क्लाइंट में गेम इकाई और उसका दृश्य प्रतिनिधित्व एक ही वस्तु थी। हमने इन इकाइयों को अलग करने का फैसला किया ताकि शॉट की गेम इकाई अब उसके दृश्यों पर निर्भर न रहे, और इससे अलग-अलग फ्रेम दर वाले उपकरणों के बीच बेहतर खेल हासिल हुआ।
खेल में बड़ी संख्या में शॉट्स का उपयोग किया जाता है, लेकिन इनके डेटा को प्रोसेस करने के लिए एल्गोरिदम काफी सरल हैं - चलना, यह तय करना कि दुश्मन को गोली लगी है या नहीं, आदि। एंटिटी कंपोनेंट सिस्टम की अवधारणा खेल में प्रक्षेप्य की गति के तर्क को व्यवस्थित करने के लिए एकदम उपयुक्त थी, इसलिए हमने इसके साथ बने रहने का फैसला किया।
इसके अलावा, हमारी सभी नई परियोजनाओं में, हम तर्क के साथ काम करने के लिए पहले से ही ECS का उपयोग कर रहे थे, और एकीकरण के लिए इस प्रतिमान को हमारे मुख्य प्रोजेक्ट पर लागू करने का समय आ गया था। किए गए कार्य के परिणामस्वरूप, हमने एक महत्वपूर्ण आवश्यकता को महसूस किया - 60 FPS पर छवियों को चलाने की क्षमता सुनिश्चित करना। हालाँकि, सभी लड़ाकू कोड ECS में स्थानांतरित नहीं किए गए थे, इसलिए इस दृष्टिकोण की क्षमता को पूरी तरह से महसूस नहीं किया जा सका। अंततः, हमने प्रदर्शन में उतना सुधार नहीं किया जितना हम चाहते थे, लेकिन हमने इसे कम भी नहीं किया, जो अभी भी इस तरह के एक मजबूत प्रतिमान और वास्तुकला बदलाव के साथ एक महत्वपूर्ण संकेतक है।
उसी समय, हमने अपने पीसी संस्करण पर काम करना शुरू किया ताकि यह देखा जा सके कि हम अपने नए ग्राफ़िक्स स्टैक के साथ किस स्तर का ग्राफ़िक्स प्राप्त कर सकते हैं। इसने यूनिटी एसआरपी का लाभ उठाना शुरू किया, जो उस समय अभी भी पूर्वावलोकन संस्करण में था और लगातार बदल रहा था। स्टीम संस्करण के लिए जो तस्वीर सामने आई वह काफी प्रभावशाली थी:
इसके अलावा, ऊपर दी गई छवि में दिखाए गए कुछ ग्राफिकल फीचर्स को शक्तिशाली मोबाइल डिवाइस में स्थानांतरित किया जा सकता है। यह विशेष रूप से Apple डिवाइस के लिए था, जिसमें ऐतिहासिक रूप से अच्छी प्रदर्शन विशेषताएँ, उत्कृष्ट ड्राइवर और हार्डवेयर और सॉफ़्टवेयर का एक बेहतरीन संयोजन होता है; यह उन्हें हमारी ओर से किसी भी अस्थायी समाधान के बिना बहुत उच्च गुणवत्ता की तस्वीर बनाने की अनुमति देता है।
हम जल्दी ही समझ गए कि केवल ग्राफ़िक्स स्टैक बदलने से छवि नहीं बदलेगी। यह भी स्पष्ट हो गया कि शक्तिशाली उपकरणों के अलावा, हमें कमज़ोर उपकरणों के लिए भी सामग्री की आवश्यकता होगी। इसलिए, हमने विभिन्न गुणवत्ता स्तरों के लिए सामग्री विकसित करने की योजना बनाना शुरू कर दिया।
इसका मतलब यह था कि मशीन, बंदूकें, नक्शे, प्रभाव और उनकी बनावट को गुणवत्ता में अलग-अलग किया जाना था, जिसका मतलब है कि अलग-अलग गुणवत्ता के लिए अलग-अलग इकाइयाँ। यानी, भौतिक मॉडल, बनावट और मशीन बनावट का सेट जो HD गुणवत्ता में काम करेगा, वह उन मशीन से अलग होगा जो अन्य गुणवत्ता में काम करेगा।
इसके अलावा, गेम में मैप्स के लिए बहुत ज़्यादा संसाधन लगाए गए हैं और इन्हें नए गुणों के अनुरूप बनाने की भी ज़रूरत है। यह भी स्पष्ट हो गया कि मौजूदा क्वालिटी मैनेजर हमारी ज़रूरतों को पूरा नहीं करता क्योंकि यह एसेट क्वालिटी को नियंत्रित नहीं करता।
इसलिए, सबसे पहले, हमें यह तय करना था कि हमारे गेम में कौन सी क्वालिटी उपलब्ध होगी। हमारे मौजूदा क्वालिटी मैनेजर के अनुभव को ध्यान में रखते हुए, हमने महसूस किया कि नए संस्करण में, हम कई निश्चित क्वालिटी चाहते थे जिन्हें उपयोगकर्ता किसी दिए गए डिवाइस के लिए अधिकतम उपलब्ध क्वालिटी के आधार पर सेटिंग्स में स्वतंत्र रूप से स्विच कर सकता है।
नई गुणवत्ता प्रणाली उपयोगकर्ता के पास मौजूद डिवाइस को निर्धारित करती है और डिवाइस मॉडल (iOS के मामले में) और GPU मॉडल (Android के मामले में) के आधार पर, हमें किसी विशिष्ट प्लेयर के लिए अधिकतम उपलब्ध गुणवत्ता निर्धारित करने की अनुमति देती है। इस मामले में, यह गुणवत्ता, साथ ही साथ सभी पिछली गुणवत्ताएँ उपलब्ध हैं।
इसके अलावा, प्रत्येक गुणवत्ता के लिए, अधिकतम FPS को 30 और 60 के बीच स्विच करने के लिए एक सेटिंग है। शुरू में, हमने लगभग पाँच गुणवत्ताएँ (ULD, LD, MD, HD, UHD) रखने की योजना बनाई थी। हालाँकि, विकास प्रक्रिया के दौरान, यह स्पष्ट हो गया कि इतनी सारी गुणवत्ताएँ विकसित होने में बहुत लंबा समय लगेगा और इससे हम QA पर भार कम नहीं कर पाएँगे। इसे ध्यान में रखते हुए, अंततः, हमने खेल में निम्नलिखित गुणवत्ताएँ बनाईं: HD, LD, और ULD। (संदर्भ के लिए, इन गुणवत्ताओं के साथ खेलने वाले दर्शकों का वर्तमान वितरण इस प्रकार है: HD - 7%, LD - 72%, ULD - 21%।)
जैसे ही हमें समझ में आया कि हमें और अधिक गुणवत्ताओं को लागू करने की आवश्यकता है, हमने उन गुणों के अनुसार परिसंपत्तियों को छाँटने का तरीका निकालना शुरू कर दिया। इस काम को सरल बनाने के लिए, हम निम्नलिखित एल्गोरिदम पर सहमत हुए: कलाकार अधिकतम गुणवत्ता (एचडी) वाली परिसंपत्तियाँ बनाएंगे, और फिर, स्क्रिप्ट और अन्य स्वचालन उपकरणों का उपयोग करके, इन परिसंपत्तियों के कुछ हिस्सों को सरल बनाया जाएगा और अन्य गुणों के लिए परिसंपत्तियों के रूप में उपयोग किया जाएगा।
इस स्वचालन प्रणाली पर काम करने की प्रक्रिया में, हमने निम्नलिखित समाधान विकसित किए:
मौजूदा मेक और मैप संसाधनों को रीफैक्टर करने के लिए बहुत काम किया गया है। मूल मेक को अलग-अलग गुणों को ध्यान में रखकर डिज़ाइन नहीं किया गया था और इसलिए, उन्हें सिंगल प्रीफ़ैब में संग्रहीत किया गया था। रीफैक्टरिंग के बाद, उनमें से बुनियादी हिस्से निकाले गए, जिनमें मुख्य रूप से उनका तर्क शामिल था, और प्रीफ़ैब वेरिएंट का उपयोग करके, एक विशिष्ट गुणवत्ता के लिए बनावट वाले वेरिएंट बनाए गए। साथ ही, हमने ऐसे उपकरण जोड़े जो गुणों के आधार पर बनावट भंडारण फ़ोल्डरों के पदानुक्रम को ध्यान में रखते हुए, एक मेक को स्वचालित रूप से विभिन्न गुणों में विभाजित कर सकते हैं।
विशिष्ट उपकरणों को विशिष्ट एसेट प्रदान करने के लिए, गेम में सभी सामग्री को बंडलों और पैक में विभाजित करना आवश्यक था। मुख्य पैक में गेम चलाने के लिए आवश्यक एसेट, सभी क्षमताओं में उपयोग की जाने वाली एसेट, साथ ही प्रत्येक प्लेटफ़ॉर्म के लिए गुणवत्ता पैक शामिल हैं: Android_LD, Android_HD, Android_ULD, iOS_LD, iOS_HD, iOS_ULD, इत्यादि।
पैक्स में परिसंपत्तियों का विभाजन रिसोर्स सिस्टम टूल की बदौलत संभव हुआ, जिसे हमारी प्लेटफ़ॉर्म टीम ने बनाया था। इस सिस्टम ने हमें परिसंपत्तियों को अलग-अलग पैकेजों में इकट्ठा करने और फिर उन्हें क्लाइंट में एम्बेड करने या उन्हें बाहरी संसाधनों, जैसे कि CDN पर अपलोड करने के लिए अलग से लेने की अनुमति दी।
सामग्री वितरित करने के लिए, हमने एक नई प्रणाली का उपयोग किया, जिसे प्लेटफ़ॉर्म टीम द्वारा भी बनाया गया था, जिसे डिलीवरी सिस्टम कहा जाता है। यह सिस्टम आपको रिसोर्स सिस्टम द्वारा बनाए गए मैनिफ़ेस्ट को प्राप्त करने और निर्दिष्ट स्रोत से संसाधन डाउनलोड करने की अनुमति देता है। यह स्रोत या तो एक मोनोलिथिक बिल्ड, व्यक्तिगत APK फ़ाइलें या एक दूरस्थ CDN हो सकता है।
प्रारंभ में, हमने संसाधन पैक संग्रहीत करने के लिए Google Play (Play Asset Delivery) और AppStore (ऑन-डिमांड संसाधन) की क्षमताओं का उपयोग करने की योजना बनाई थी, लेकिन एंड्रॉइड प्लेटफ़ॉर्म पर, स्वचालित क्लाइंट अपडेट से जुड़ी कई समस्याएं थीं, साथ ही संग्रहीत संसाधनों की संख्या पर प्रतिबंध भी थे।
इसके अलावा, हमारे आंतरिक परीक्षणों से पता चला कि CDN के साथ सामग्री वितरण प्रणाली सबसे अच्छा काम करती है और सबसे अधिक स्थिर होती है, इसलिए हमने संसाधनों को स्टोर में संग्रहीत करना छोड़ दिया और उन्हें अपने क्लाउड में संग्रहीत करना शुरू कर दिया।
जब रीमास्टर पर मुख्य काम पूरा हो गया, तो इसे रिलीज़ करने का समय आ गया। हालाँकि, हम जल्दी ही समझ गए कि 3 जीबी का मूल नियोजित आकार एक खराब डाउनलोड अनुभव था, जबकि बाजार में कई लोकप्रिय गेम के लिए उपयोगकर्ताओं को 5-10 जीबी डेटा डाउनलोड करने की आवश्यकता होती है। हमारा सिद्धांत यह था कि जब तक हम अपने रीमास्टर्ड गेम को बाजार में जारी करेंगे, तब तक उपयोगकर्ता इस नई वास्तविकता के आदी हो जाएँगे, लेकिन अफसोस।
दूसरे शब्दों में, खिलाड़ियों को मोबाइल गेम के लिए इस तरह की बड़ी फ़ाइलों की आदत नहीं थी। हमें इस समस्या का जल्दी से समाधान खोजने की ज़रूरत थी। हमने इसके बाद कई बार HD गुणवत्ता के बिना एक संस्करण जारी करने का फैसला किया, लेकिन हमने इसे बाद में अपने उपयोगकर्ताओं तक पहुँचाया।
रीमास्टर के विकास के समानांतर, हमने प्रोजेक्ट परीक्षण को स्वचालित करने के लिए सक्रिय रूप से काम किया। QA टीम ने यह सुनिश्चित करने में बहुत अच्छा काम किया है कि प्रोजेक्ट की स्थिति को स्वचालित रूप से ट्रैक किया जा सके। फिलहाल, हमारे पास वर्चुअल मशीनों वाले सर्वर हैं जहाँ गेम चलता है। स्व-लिखित परीक्षण ढांचे का उपयोग करके, हम स्क्रिप्ट के साथ प्रोजेक्ट में कोई भी बटन दबा सकते हैं - और डिवाइस पर सीधे परीक्षण करते समय विभिन्न परिदृश्यों को चलाने के लिए उन्हीं स्क्रिप्ट का उपयोग किया जाता है।
हम इस सिस्टम को विकसित करना जारी रख रहे हैं: स्थिरता, प्रदर्शन और सही तर्क निष्पादन की जाँच करने के लिए सैकड़ों लगातार चलने वाले परीक्षण पहले ही लिखे जा चुके हैं। परिणाम एक विशेष डैशबोर्ड में प्रदर्शित किए जाते हैं जहाँ हमारे QA विशेषज्ञ, डेवलपर्स के साथ मिलकर सबसे अधिक समस्याग्रस्त क्षेत्रों (परीक्षण चलाने से वास्तविक स्क्रीनशॉट सहित) की विस्तार से जाँच कर सकते हैं।
मौजूदा सिस्टम को चालू करने से पहले, रिग्रेशन टेस्टिंग में बहुत समय लगा (प्रोजेक्ट के पुराने वर्शन पर लगभग एक सप्ताह), जो वॉल्यूम और कंटेंट की मात्रा के मामले में मौजूदा वर्शन से बहुत कम था। लेकिन स्वचालित परीक्षण के लिए धन्यवाद, गेम के मौजूदा वर्शन का परीक्षण केवल दो रातों के लिए किया जाता है; इसे और बेहतर बनाया जा सकता है, लेकिन वर्तमान में, हम सिस्टम से जुड़े डिवाइस की संख्या से सीमित हैं।
रीमास्टर के पूरा होने की ओर, Apple टीम ने हमसे संपर्क किया और हमें नए उत्पाद प्रस्तुति में भाग लेने का अवसर दिया ताकि हमारे नए ग्राफ़िक्स का उपयोग करके नए Apple A14 बायोनिक चिप (2020 के पतन में नए iPads के साथ जारी) की क्षमताओं का प्रदर्शन किया जा सके। इस मिनी प्रोजेक्ट पर काम के दौरान, एक पूरी तरह से काम करने वाला HD संस्करण बनाया गया, जो 120 FPS पर Apple चिप्स पर चलने में सक्षम था। इसके अलावा, नई चिप की शक्ति को प्रदर्शित करने के लिए कई ग्राफ़िकल सुधार जोड़े गए।
एक प्रतिस्पर्धी और कठिन चयन के परिणामस्वरूप, हमारा गेम Apple इवेंट की शरदकालीन प्रस्तुति में शामिल किया गया! पूरी टीम इस इवेंट को देखने और जश्न मनाने के लिए एकत्र हुई, और यह वाकई शानदार था!
2021 में गेम के रीमास्टर्ड वर्शन के लॉन्च से पहले ही एक नया टास्क सामने आया था। कई उपयोगकर्ताओं ने नेटवर्क समस्याओं के बारे में शिकायत की थी, जिसका मूल उस समय हमारा मौजूदा समाधान था, फोटॉन ट्रांसपोर्ट लेयर, जिसका उपयोग फोटॉन सर्वर SDK के साथ काम करने के लिए किया जाता था। एक और समस्या बड़ी और गैर-मानकीकृत संख्या में RPC की उपस्थिति थी जो एक यादृच्छिक क्रम में सर्वर पर भेजी जाती थी।
इसके अलावा, विश्वों को सिंक्रनाइज़ करने और मैच की शुरुआत में संदेश कतार को ओवरफ्लो करने में भी समस्याएं थीं, जिससे महत्वपूर्ण देरी हो सकती थी।
स्थिति को सुधारने के लिए, हमने नेटवर्क मैच स्टैक को अधिक पारंपरिक मॉडल की ओर ले जाने का निर्णय लिया, जहां सर्वर के साथ संचार पैकेट और गेम स्टेट प्राप्त करने के माध्यम से होता है, न कि RPC कॉल के माध्यम से।
नए ऑनलाइन मैच आर्किटेक्चर को वर्ल्डस्टेट कहा गया और इसका उद्देश्य गेमप्ले से फोटॉन को हटाना था।
लाइटनेटलिब लाइब्रेरी पर आधारित फोटोन से यूडीपी तक परिवहन प्रोटोकॉल को प्रतिस्थापित करने के अलावा, इस नई वास्तुकला में क्लाइंट-सर्वर संचार प्रणाली को सुव्यवस्थित करना भी शामिल था।
इस सुविधा पर काम करने के परिणामस्वरूप, हमने सर्वर साइड पर लागत कम कर दी (विंडोज़ से लिनक्स पर स्विच करना और फोटॉन सर्वर एसडीके लाइसेंस को त्यागना), एक ऐसा प्रोटोकॉल तैयार किया जो उपयोगकर्ता के अंतिम उपकरणों के लिए बहुत कम मांग वाला है, जिससे सर्वर और क्लाइंट के बीच स्टेट डिसिंक्रोनाइज़ेशन से जुड़ी समस्याओं की संख्या कम हो गई, और नई PvE सामग्री विकसित करने का अवसर पैदा हुआ।
रातों-रात पूरे गेम कोड को बदलना असंभव होगा, इसलिए वर्ल्डस्टेट पर काम कई चरणों में विभाजित किया गया।
पहला चरण क्लाइंट और सर्वर के बीच संचार प्रोटोकॉल का पूर्ण रूप से नया स्वरूप था, और मेच की आवाजाही को नई रेल पर स्थानांतरित कर दिया गया था। इसने हमें गेम के लिए एक नया मोड बनाने की अनुमति दी: PvE। धीरे-धीरे, मैकेनिक्स सर्वर पर जाने लगे, विशेष रूप से नवीनतम वाले (मेच को नुकसान और गंभीर क्षति)। पुराने कोड को वर्ल्डस्टेट मैकेनिज्म में धीरे-धीरे स्थानांतरित करने पर काम जारी है और इस साल हमारे पास कई अपडेट भी होंगे।
2022 में, हमने एक नए प्लैटफ़ॉर्म पर लॉन्च किया: Facebook Cloud. इस प्लैटफ़ॉर्म के पीछे की अवधारणा दिलचस्प थी: क्लाउड में एमुलेटर पर गेम चलाना और उन्हें स्मार्टफ़ोन और पीसी पर ब्राउज़र में स्ट्रीम करना, गेम चलाने के लिए अंतिम खिलाड़ी के पास शक्तिशाली पीसी या स्मार्टफ़ोन होने की आवश्यकता नहीं है; केवल एक स्थिर इंटरनेट कनेक्शन की आवश्यकता है।
डेवलपर की ओर से, दो प्रकार के बिल्ड वितरित किए जा सकते हैं, जिन्हें मुख्य रूप से प्लेटफ़ॉर्म द्वारा उपयोग किया जाएगा: एंड्रॉइड बिल्ड और विंडोज बिल्ड। हमने इस प्लेटफ़ॉर्म के साथ अपने अधिक अनुभव के कारण पहला रास्ता चुना।
फेसबुक क्लाउड पर अपना गेम लॉन्च करने के लिए, हमें कई संशोधन करने की ज़रूरत थी, जैसे गेम में प्राधिकरण को फिर से करना और कर्सर नियंत्रण जोड़ना। हमें सभी अंतर्निहित संसाधनों के साथ एक बिल्ड तैयार करने की भी आवश्यकता थी क्योंकि प्लेटफ़ॉर्म CDN का समर्थन नहीं करता था, और हमें अपने एकीकरण को कॉन्फ़िगर करने की आवश्यकता थी, जो हमेशा एमुलेटर पर सही ढंग से नहीं चल सकता था।
ग्राफिक्स स्टैक की कार्यक्षमता सुनिश्चित करने के लिए ग्राफिक्स पक्ष पर भी काफी काम किया गया था, क्योंकि फेसबुक एमुलेटर वास्तविक एंड्रॉइड डिवाइस नहीं थे और ड्राइवर कार्यान्वयन और संसाधन प्रबंधन के संदर्भ में उनकी अपनी विशेषताएं थीं।
हालाँकि, हमने देखा कि इस प्लेटफ़ॉर्म के उपयोगकर्ताओं को कई समस्याओं का सामना करना पड़ा - अस्थिर कनेक्शन और एमुलेटर का अस्थिर संचालन, और इसलिए फेसबुक ने 2024 की शुरुआत में अपने प्लेटफ़ॉर्म को बंद करने का फैसला किया।
प्रोग्रामर्स की ओर से जो लगातार होता रहता है और जिस पर इतने छोटे लेख में विस्तार से चर्चा नहीं की जा सकती, वह है परियोजना के तकनीकी जोखिमों के साथ नियमित रूप से काम करना, तकनीकी मैट्रिक्स की नियमित निगरानी, मेमोरी के साथ निरंतर काम करना और संसाधनों का अनुकूलन, पार्टनर SDK के तीसरे पक्ष के समाधानों में समस्याओं की खोज करना, विज्ञापन एकीकरण और बहुत कुछ।
इसके अलावा, हम गंभीर क्रैश और ANR को ठीक करने पर शोध और व्यावहारिक कार्य जारी रखते हैं। जब कोई प्रोजेक्ट इतनी बड़ी संख्या में पूरी तरह से अलग-अलग डिवाइस पर चलता है, तो यह अपरिहार्य है।
अलग से, हम उन लोगों की व्यावसायिकता पर ध्यान देना चाहेंगे जो समस्याओं के कारणों का पता लगाने के लिए काम करते हैं। ये तकनीकी समस्याएँ अक्सर प्रकृति में जटिल होती हैं और कई विश्लेषणात्मक प्रणालियों से डेटा को एक दूसरे के ऊपर रखना आवश्यक होता है, साथ ही कारण का पता लगाने से पहले कुछ गैर-तुच्छ प्रयोग भी करने होते हैं। अक्सर, अधिकांश जटिल समस्याओं में लगातार पुनरुत्पादित करने योग्य मामला नहीं होता है जिसका परीक्षण किया जा सके, इसलिए उन्हें ठीक करने के लिए अक्सर अनुभवजन्य डेटा और हमारे पेशेवर अनुभव का उपयोग किया जाता है।
किसी परियोजना में समस्याएं ढूंढने के लिए हम जिन उपकरणों और संसाधनों का उपयोग करते हैं, उनके बारे में कुछ शब्द कहे जाने चाहिए।
यह तकनीकी सुधारों की एक छोटी सूची है जो परियोजना के अस्तित्व के दौरान हुई है। परियोजना में जो कुछ भी हासिल हुआ है, उसे सूचीबद्ध करना मुश्किल है क्योंकि परियोजना लगातार विकसित हो रही है, और तकनीकी प्रबंधक अंतिम उपयोगकर्ताओं और स्टूडियो के अंदर इसके साथ काम करने वाले लोगों, जिसमें स्वयं डेवलपर्स और अन्य विभाग शामिल हैं, दोनों के लिए उत्पाद के प्रदर्शन को बेहतर बनाने के लिए लगातार योजनाएँ तैयार करने और उन्हें लागू करने पर काम कर रहे हैं।
हमारे पास अभी भी कई सुधार हैं जो अगले दशक में उत्पाद में होंगे, और हमें आशा है कि हम इन्हें अपने अगले लेखों में साझा कर सकेंगे।
जन्मदिन की शुभकामनाएं, वॉर रोबोट्स, और तकनीकी विशेषज्ञों की विशाल टीम को धन्यवाद, जिन्होंने यह सब संभव बनाया!