क्लाइंट-साइड भविष्यवाणी कैसे काम करती है?


33

मैंने वाल्व + गैफ़रॉन और Google के सैकड़ों पृष्ठ पढ़े हैं, लेकिन जिस भी कारण से मुझे क्लाइंट भविष्यवाणी के आसपास अपना सिर नहीं मिला।

मेरी समझ में, मूल समस्या यह है:

  • ग्राहक A पर इनपुट भेजता है T0
  • सर्वर पर इनपुट प्राप्त होता है T1
  • सभी ग्राहकों को यह परिवर्तन प्राप्त होता है T2

पर T2फिर भी, ग्राहक भविष्यवाणी का उपयोग कर, ग्राहक एक अब करने की स्थिति उचित है T4

आप यह कैसे सुनिश्चित करते हैं कि क्लाइंट ए, जब भविष्यवाणी करता है कि सर्वर आंदोलन के अनुरोध को स्वीकार करेगा, सर्वर से आगे नहीं होगा? जाहिर है कि हर समय वे आगे रहते हैं, इस परिणाम में वापस जाने के लिए जहां सर्वर ने उन्हें आखिरी बार देखा था। मेरे द्वारा किए गए सभी सुधारों के साथ, यह तब भी ध्यान देने योग्य होता है जब आप रुकते हैं, क्योंकि सर्वर आपके पीछे रुक जाता है

जवाबों:


35

मैंने इस पर कई लेख लिखे । यह उन्हीं विचारों पर आधारित है, जो आपने कहीं और पढ़े हैं, लेकिन बहुत विस्तृत और (मुझे आशा है) सुलभ तरीके से समझाया गया है।

विशेष रूप से, क्लाइंट-साइड भविष्यवाणी के बारे में लेख यह एक है


उत्कृष्ट लेख :-) मुझे श्रृंखला का चौथा भाग देखना अच्छा लगेगा। एक छोटे से सुझाव के रूप में, प्रत्येक लेख के अंत में अगले भाग का लिंक निश्चित रूप से नेविगेशन में सुधार करेगा।
या मैपर

5
@ORMapper - मैंने आखिरकार 4 वां लेख लिखा! gabrielgambetta.com/fpm4.html
ggambett

आपकी लेख श्रृंखला के लिए कुडोस :-) बहुत उपयोगी, धन्यवाद :-)
या मैपर

सभी लेख (मैं पा सकता हूं) जो संग्रहीत स्नैपशॉट का उपयोग करके अतीत के पुनर्निर्माण के बारे में बात करते हैं, उदाहरण के लिए शूटिंग लेते हैं। क्या यह आंदोलन के लिए भी लागू होता है? मैं कल्पना कर सकता हूं कि अगर अन्य खिलाड़ी आपस में टकरा सकते हैं, तो आंदोलन की पुनरावृत्ति दूसरे खिलाड़ियों के लिए कुछ बड़े अंतर पैदा कर सकती है। मान लीजिए कि दो खिलाड़ी एक-दूसरे के खिलाफ चलते हैं और उनमें से कुछ टकराव बिंदु से दूर "कुछ कदम" आगे बढ़ते हैं। यह स्टॉप कमांड लैग की वजह से देर से आता है इसलिए अगर हम दुनिया को फिर से संगठित करते हैं, तो दोनों खिलाड़ी बहुत अलग स्थिति में होंगे
लोप

यह एक दिलचस्प सवाल है। दुर्भाग्य से, मेरे पास कोई निश्चित जवाब नहीं है। मुझे लगता है कि यह इस बात पर निर्भर करता है कि खेल के लिए आंदोलन कितने महत्वपूर्ण हैं; क्या तुम किसी और से टकराते हो और कुछ नहीं होता? उस मामले में सर्वर शायद परवाह नहीं करता है, इसे एक भविष्यवाणी की गलती के रूप में देखा जाता है (हम सभी ने इसे चोक पॉइंट्स में देखा है, ठीक है।)। क्या आप संपर्क पर दूसरे खिलाड़ी को मारते हैं? उस स्थिति में यह सही होना बहुत अधिक महत्वपूर्ण है और यह फिर से तैयार करने लायक हो सकता है। ध्यान दें कि किसी बिंदु पर आपको कुछ पैकेटों को "बहुत पुराना" के रूप में त्यागने की आवश्यकता होती है, अन्यथा आप किसी भी समय t = 0 से संभावित रूप से बदलते होंगे।
ggambett

4

मैंने वास्तव में इसे लागू नहीं किया है (इसलिए कुछ समस्याएं हो सकती हैं जिन्हें मैं तुरंत नहीं देख रहा हूं), लेकिन मुझे लगा कि मैं मदद करने की कोशिश करूंगा।

यहां आपने जो कहा वह हो रहा है:

क्लाइंट A, T0 पर इनपुट भेजता है

सर्वर T1 पर इनपुट प्राप्त करता है

सभी क्लाइंट T2 पर परिवर्तन प्राप्त करते हैं

T2 पर, क्लाइंट भविष्यवाणी का उपयोग करते हुए, क्लाइंट A अब T4 के लिए उपयुक्त स्थिति में है।

शायद सर्वर के समय के संदर्भ में सोचना उपयोगी होगा। इसका (शायद) बहुत ही समान है कि प्रक्षेप कैसे काम करता है।

हर कमांड को सर्वर टाइम के साथ भेजा जाता है। यह सर्वर समय एक मैच की शुरुआत में सर्वर टिक के लिए क्वेरी करके, पिंग समय के लिए क्षतिपूर्ति करके लगा है। क्लाइंट पर आपके पास अपनी स्थानीय टिक संख्या होती है, और आपके द्वारा भेजे जाने वाले प्रत्येक कमांड को सर्वर टिक में बदल दिया जाता है (यह एक साधारण घटाव ऑपरेशन है)

इसके अलावा, क्लाइंट हमेशा "अतीत में" प्रस्तुत कर रहा है। तो आप यह मान लेते हैं कि ग्राहक जिस दुनिया को देखता है, वह कहता है कि सर्वर का समय वास्तव में क्या है।

तो चलिए आपके उदाहरण को सर्वर टाइम (S द्वारा निर्दिष्ट) के साथ फिर से जोड़ते हैं।

क्लाइंट T0 पर सर्वर समय S0 के साथ इनपुट भेजता है (जो मैं अनुमान लगा रहा हूं वह वास्तव में "सर्वर टाइम माइनस इंटरपोलेशन टाइम का क्लाइंट प्रतिनिधित्व है")। क्लाइंट सर्वर से प्रतिक्रिया का इंतजार नहीं करता है और तुरंत चला जाता है।

सर्वर T1 पर इनपुट प्राप्त करता है। क्लाइंट द्वारा दिए गए सर्वर समय S0 पर सर्वर के ग्राहक की आधिकारिक स्थिति के आंकड़े। क्लाइंट को भेजता है।

क्लाइंट T2 पर आधिकारिक स्थिति प्राप्त करता है (अभी भी सर्वर समय S0 के पदनाम के साथ)। ग्राहक पिछली घटनाओं के समय की कुछ पिछली राशि का ट्रैक रखता है (शायद सभी अपुष्ट भविष्यवाणियों की सिर्फ एक कतार)।

यदि अनुमानित स्थिति / वेग / जो कुछ भी सर्वर S0 पर वापस भेजता है वह ग्राहक द्वारा S0 में संग्रहीत किए गए से भिन्न है, तो क्लाइंट इसे किसी भी तरह से संभालता है। या तो खिलाड़ी को उनके पिछले स्थान पर वापस भेज दिया जाए, या पिछले इनपुट का पुनरुत्पादन किया जाए, या शायद कुछ और जो मैंने नहीं सोचा है।


3
अतीत में क्लाइंट रेंडरिंग के बारे में थोड़ा को छोड़कर यह सब सही है। सर्वर के सापेक्ष, क्लाइंट वास्तव में भविष्य में प्रदान कर रहा है! सर्वर जानता है कि उसके पास प्रत्येक ग्राहक की जानकारी पुरानी है और तब से प्रत्येक ग्राहक पहले से ही बदल चुका होगा।
काइलोटन

2

वास्तव में जीथब में एक ओपन-सोर्स कार्यान्वयन है जो दिखाता है कि यह कैसे किया जाता है। की जाँच करें Lance.gg

github repo: https://github.com/lance-gg/lance

क्लाइंट भविष्यवाणी कोड को मॉड्यूल में लागू किया जाता है src/syncStrategies/ExtrapolateStrategy.js

एक्सट्रपलेशन के अलावा, दो अवधारणाएं हैं जिन्हें मैंने ऊपर उल्लेख नहीं किया था:

  1. वृद्धिशील झुकने। मूल रूप से सर्वर सुधार को एक साथ लागू करने के बजाय, आप डेल्टा को छोटे वेतन वृद्धि में लागू करते हैं। इस तरह से दूरस्थ वस्तुएं धीरे-धीरे अपनी स्थिति को सर्वर के पदों से मिलान करने के लिए समायोजित करेंगी। झुकने, वेग झुकने, कोण झुकने, और कोणीय वेग झुकने की स्थिति है। इसके अलावा, आप अलग-अलग वस्तुओं के लिए अलग-अलग झुकने वाले कारक चाहते हो सकते हैं।
  2. स्टेप रि-एक्टमेंट। तथ्य यह है कि डेटा अतीत में है इसका मतलब है कि आप सर्वर डेटा समय पर रोलबैक कर सकते हैं, और उस बिंदु से पुनरारंभ कर सकते हैं। बेशक आपको अभी भी कूदने के बजाय नए-नए स्थान की ओर झुकना होगा।

1

क्लाइंट A सर्वर से हमेशा आगे रहता है - लेकिन इससे कोई फर्क नहीं पड़ता। आपको केवल क्लाइंट को वापस स्नैप करना होगा यदि सर्वर कहता है कि रिपोर्ट की गई स्थिति में कोई समस्या थी, जिस पर क्लाइंट ने सुधार किए गए सभी मानों को सही मानों के साथ त्रुटि के बाद फिर से चलाता है, ताकि इसे राज्य के अनुकूल लाया जा सके। सर्वर के साथ।

ऐसा करने के लिए, ग्राहक को अपनी पिछली स्थिति और पिछले अपडेट को याद रखना होगा। यह केवल कुछ सरल मान हो सकते हैं जैसे कि स्थिति, वेग, अभिविन्यास, इस तरह की चीज। सर्वर समय-समय पर एक पावती भेजेगा कि विभिन्न ग्राहक अपडेट वैध थे, जिसका अर्थ है कि अब उन्हें ग्राहक से भुलाया जा सकता है। यदि सर्वर हालांकि रिपोर्ट करता है कि एक अद्यतन अमान्य था, तो क्लाइंट स्थिति उस बिंदु पर वापस आ जाती है और भविष्य के परिवर्तन उस संशोधित स्थिति पर लागू होते हैं।

वाल्व लेख के नीचे कुछ अतिरिक्त लिंक हैं जो पढ़ने योग्य हैं - यह उनमें से एक है: https://developer.valvesoftware.com/wiki/Prediction


इसलिए, क्या मैं यह सोचने में सही हूं कि क्लाइंट (के t=4बारे में ) जानकारी प्राप्त करता है t=2, इसलिए यह t=2वस्तुओं को लाने के लिए अपडेट को फिर से चलाने के लिए राज्य को रीसेट करता t=2है t=4?
जॉर्ज डकेट

मैं अभी भी इसे किसी कारण से नहीं समझ रहा हूं। सर्वर को केवल इनपुट्स प्लेयर की स्थिति नहीं बताई जा रही है। तो खिलाड़ी अंतिम स्थिति से आगे बढ़ रहा है कि सर्वर ने कहा था कि यह था। इनपुट लगाया गया है। सर्वर को सूचित किया जाता है। सर्वर सभी के लिए इनपुट की पुष्टि करता है। सभी आदेशों को स्वीकार किए जाने पर, सर्वर अभी भी क्लाइंट ए के पीछे रहेगा - इसलिए जब क्लाइंट ए बंद हो जाता है, तो उसका चरित्र तुरंत बंद हो जाएगा, फिर सर्वर स्थान पर वापस स्लाइड करें जब वह स्टॉप पुष्टि प्राप्त करता है।
क्रिस इवांस

@GeorgeDuckett: हाँ (हालाँकि इसे t = 4 होना ज़रूरी नहीं है, यह तब भी हो सकता है जब भी किसी विसंगति का पता लगाया जाता है, और किसी भी संख्या में पुन: लागू अपडेट हो सकता है।)
Kylotan

@ChrisEvans: ज्ञात स्थिति + इनपुट के आधार पर परिवर्तन वैसे भी राज्य भेजने के बराबर हैं। रोक उदाहरण के लिए, कि अपने आप में एक इनपुट है, और सर्वर अभी भी आंदोलन का अनुकरण कर रहा है जब तक कि वह इनपुट प्राप्त नहीं करता है। निरंतर विलंबता मानकर, सर्वर खिलाड़ी को ठीक उसी स्थिति में ले जाना बंद कर देगा, जिसे क्लाइंट ने चलते समय देखा था, क्योंकि क्लाइंट सर्वर से आगे था। (वास्तविक दुनिया में, विलंबता अलग-अलग होती है, इसलिए आप इसे सुचारू करने के लिए थोड़ा सा प्रक्षेप करते हैं।)
कियलोतन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.