मैं मध्यम-स्तर के मल्टीप्लेयर के साथ एक आइसोमेट्रिक 2 डी गेम पर काम कर रहा हूं, लगभग 20-30 खिलाड़ी एक बार एक निरंतर सर्वर से जुड़े। मुझे जगह में एक अच्छा आंदोलन भविष्यवाणी कार्यान्वयन प्राप्त करने में कुछ कठिनाई हुई है।
भौतिकी / आंदोलन
खेल में एक वास्तविक भौतिकी कार्यान्वयन नहीं है, लेकिन आंदोलन को लागू करने के लिए मूल सिद्धांतों का उपयोग करता है। लगातार मतदान इनपुट के बजाय, राज्य परिवर्तन (यानी / माउस डाउन / अप / मूव इवेंट) का उपयोग उस चरित्र इकाई की स्थिति को बदलने के लिए किया जाता है जिसे खिलाड़ी नियंत्रित कर रहा है। खिलाड़ी की दिशा (यानी / उत्तर-पूर्व) एक स्थिर गति के साथ संयुक्त होती है और एक सच्चे 3 डी वेक्टर में बदल जाती है - इकाई का वेग।
मुख्य गेम लूप में, "ड्रा" से पहले "अपडेट" कहा जाता है। अद्यतन तर्क "भौतिकी अद्यतन कार्य" को चलाता है जो गैर-शून्य वेग के साथ सभी संस्थाओं को ट्रैक करता है, संस्थाओं की स्थिति को बदलने के लिए बहुत बुनियादी एकीकरण का उपयोग करता है। उदाहरण के लिए: unit.Position + = unit.Velocity.Scale (ElapsedTime.Seconds) (जहां "सेकंड" एक फ़्लोटिंग पॉइंट मान है, लेकिन वही दृष्टिकोण मिलीसेकंड पूर्णांक मानों के लिए काम करेगा)।
प्रमुख बिंदु यह है कि आंदोलन के लिए किसी भी प्रक्षेप का उपयोग नहीं किया जाता है - अल्पविकसित भौतिकी इंजन में "पिछले राज्य" या "वर्तमान स्थिति" की कोई अवधारणा नहीं है, केवल एक स्थिति और वेग है।
स्टेट चेंज एंड अपडेट पैकेट्स
जब चरित्र इकाई का वेग खिलाड़ी परिवर्तनों को नियंत्रित कर रहा होता है, तो एक "चाल अवतार" पैकेट को सर्वर पर भेजा जाता है जिसमें इकाई की क्रिया प्रकार (स्टैंड, वॉक, रन), दिशा (उत्तर-पूर्व), और वर्तमान स्थिति होती है। यह इस बात से अलग है कि 3D प्रथम व्यक्ति गेम कैसे काम करता है। एक 3 डी गेम में खिलाड़ी के चारों ओर घूमते समय वेग (दिशा) फ्रेम को फ्रेम में बदल सकता है। हर राज्य में बदलाव को प्रभावी ढंग से प्रति फ्रेम एक पैकेट प्रेषित किया जाएगा, जो बहुत महंगा होगा। इसके बजाय, 3 डी गेम राज्य परिवर्तनों को नजरअंदाज करते हैं और एक निश्चित अंतराल पर "राज्य अद्यतन" पैकेट भेजते हैं - कहते हैं, हर 80-150ms।
चूँकि मेरे खेल में गति और दिशा अद्यतन बहुत कम होते हैं, इसलिए मैं हर राज्य में बदलाव भेज सकता हूं। हालाँकि सभी भौतिकी सिमुलेशन समान गति से होते हैं और नियतात्मक होते हैं, लेकिन विलंबता अभी भी एक मुद्दा है। उस कारण से, मैं नियमित स्थिति अपडेट पैकेट (एक 3 डी गेम के समान) भेजता हूं, लेकिन बहुत कम अक्सर - अभी हर 250ms पर, लेकिन मुझे अच्छी भविष्यवाणी के साथ संदेह है कि मैं इसे आसानी से 500ms तक बढ़ा सकता हूं। सबसे बड़ी समस्या यह है कि मैं अब आदर्श से भटक गया हूं - अन्य सभी दस्तावेज, गाइड, और नमूने ऑनलाइन नियमित अपडेट भेजते हैं और दोनों राज्यों के बीच अंतर करते हैं। यह मेरी वास्तुकला के साथ असंगत लगता है, और मुझे एक बेहतर आंदोलन भविष्यवाणी एल्गोरिथ्म के साथ आने की जरूरत है जो एक (बहुत ही बुनियादी) "नेटवर्कयुक्त भौतिकी" वास्तुकला के करीब है।
सर्वर तब पैकेट प्राप्त करता है और एक स्क्रिप्ट के आधार पर आंदोलन के प्रकार से खिलाड़ियों की गति निर्धारित करता है (क्या खिलाड़ी चलाने में सक्षम है? खिलाड़ी की दौड़ने की गति प्राप्त करें)। एक बार इसकी गति होने के बाद, यह एक वेक्टर - इकाई के वेग को प्राप्त करने की दिशा के साथ इसे जोड़ता है। कुछ धोखा का पता लगाने और बुनियादी सत्यापन होता है, और सर्वर पक्ष पर इकाई वर्तमान वेग, दिशा और स्थिति के साथ अद्यतन की जाती है। खिलाड़ियों को आंदोलन के अनुरोध के साथ सर्वर को बाढ़ से रोकने के लिए मूल थ्रॉटलिंग भी किया जाता है।
अपनी स्वयं की इकाई को अपडेट करने के बाद, सर्वर एक "अवतार स्थिति अपडेट" पैकेट को अन्य सभी खिलाड़ियों को सीमा के भीतर प्रसारित करता है। स्थिति अद्यतन पैकेट का उपयोग दूरस्थ क्लाइंट के ग्राहक पक्ष भौतिकी सिमुलेशन (विश्व स्थिति) को अपडेट करने और भविष्यवाणी और अंतराल क्षतिपूर्ति करने के लिए किया जाता है।
भविष्यवाणी और अंतराल मुआवजा
जैसा कि ऊपर उल्लेख किया गया है, ग्राहक अपनी स्थिति के लिए आधिकारिक हैं। धोखाधड़ी या विसंगतियों के मामलों को छोड़कर, क्लाइंट के अवतार को सर्वर द्वारा कभी भी रिपॉजिट नहीं किया जाएगा। क्लाइंट के अवतार के लिए कोई एक्सट्रपलेशन ("अभी और सही बाद में") आवश्यक है - जो खिलाड़ी देखता है वह सही है। हालांकि, सभी दूरस्थ संस्थाओं के लिए किसी प्रकार के एक्सट्रपलेशन या इंटरपोलेशन की आवश्यकता होती है जो आगे बढ़ रहे हैं। क्लाइंट के स्थानीय सिमुलेशन / भौतिकी इंजन के भीतर कुछ प्रकार की भविष्यवाणी और / या क्षतिपूर्ति स्पष्ट रूप से आवश्यक है।
समस्या का
मैं विभिन्न एल्गोरिदम के साथ संघर्ष कर रहा हूं, और कई प्रश्न और समस्याएं हैं:
क्या मुझे अतिरिक्त, इंटरपोलिंग, या दोनों होना चाहिए? मेरी "आंत की भावना" यह है कि मुझे वेग के आधार पर शुद्ध एक्सट्रपलेशन का उपयोग करना चाहिए। राज्य परिवर्तन ग्राहक द्वारा प्राप्त किया जाता है, ग्राहक एक "अनुमानित" वेग की गणना करता है जो अंतराल के लिए क्षतिपूर्ति करता है, और नियमित भौतिकी प्रणाली बाकी काम करता है। हालांकि, यह अन्य सभी नमूना कोड और लेखों के लिए बाधाओं पर लगता है - वे सभी कई राज्यों को संग्रहीत करते हैं और भौतिकी इंजन के बिना प्रक्षेप करते हैं।
जब एक पैकेट आता है, तो मैंने पैकेट की स्थिति को पैकेट के वेग के साथ एक निश्चित समय अवधि (जैसे, 200ms) पर प्रक्षेपित करने की कोशिश की है। फिर मैं एक नए वेक्टर की गणना करने के लिए प्रक्षेपित स्थिति और वर्तमान "त्रुटि" स्थिति के बीच का अंतर लेता हूं और उस इकाई पर वेग के बजाय जो भेजा गया था। हालाँकि, धारणा यह है कि उस समय के अंतराल में एक और पैकेट आ जाएगा, और अगले पैकेट के आने पर "अनुमान" करना अविश्वसनीय रूप से मुश्किल है - खासकर जब से वे सभी निश्चित अंतराल (यानी / साथ ही राज्य परिवर्तन) पर नहीं आते हैं। क्या अवधारणा मौलिक रूप से त्रुटिपूर्ण है, या यह सही है लेकिन कुछ सुधार / समायोजन की आवश्यकता है?
जब एक रिमोट प्लेयर बंद हो जाता है तो क्या होता है? मैं तुरंत इकाई को रोक सकता हूं, लेकिन यह "गलत" स्थान पर तब तक तैनात रहेगा जब तक यह फिर से नहीं चलता। यदि मैं एक वेक्टर का अनुमान लगाता हूं या प्रक्षेप करने की कोशिश करता हूं, तो मेरे पास एक मुद्दा है क्योंकि मैं पिछले राज्य को संग्रहीत नहीं करता हूं - भौतिकी इंजन का यह कहने का कोई तरीका नहीं है "आपको स्थिति एक्स तक पहुंचने के बाद बंद करने की आवश्यकता है"। यह बस एक वेग को समझता है, अधिक जटिल कुछ भी नहीं है। मैं "पैकेट आंदोलन राज्य" की जानकारी को संस्थाओं या भौतिकी इंजन से जोड़ने के लिए अनिच्छुक हूं, क्योंकि यह बाकी गेम इंजन में बुनियादी डिजाइन सिद्धांतों और ब्लीड्स नेटवर्क कोड का उल्लंघन करता है।
संस्थाओं के टकरा जाने पर क्या होना चाहिए? तीन परिदृश्य हैं - नियंत्रित करने वाला खिलाड़ी स्थानीय रूप से टकराता है, दो इकाइयाँ स्थिति अद्यतन के दौरान सर्वर पर टकराती हैं, या एक दूरस्थ इकाई अद्यतन स्थानीय ग्राहक से टकराती है। सभी मामलों में मैं अनिश्चित हूं कि टकराव को कैसे संभालना है - धोखा देने से अलग, दोनों राज्य "सही" हैं, लेकिन अलग-अलग समय पर। एक दूरस्थ इकाई के मामले में यह एक दीवार के माध्यम से चलने को आकर्षित करने के लिए समझ में नहीं आता है, इसलिए मैं स्थानीय ग्राहक पर टकराव का पता लगाता हूं और इसे "बंद" करने का कारण बनता हूं। उपरोक्त बिंदु # 2 के आधार पर, मैं एक "सही वेक्टर" की गणना कर सकता हूं जो लगातार इकाई को "दीवार के माध्यम से" स्थानांतरित करने की कोशिश करता है जो कभी भी सफल नहीं होगा - जब तक कि त्रुटि बहुत अधिक न हो जाए, रिमोट अवतार वहां अटक जाता है और यह "स्नैप" में हो जाता है स्थान। खेल इसके आसपास कैसे काम करते हैं?