मल्टीप्लेयर प्लेटफ़ॉर्मर - क्या सर्वर पर एकल क्लाइंट के साथ सर्वर सुधार की आवश्यकता होती है?


10

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

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

यदि आप गेम नेटवर्किंग से परिचित हैं, तो मुझे लगता है कि आप संदर्भ अनुभागों को छोड़ सकते हैं, हालाँकि मैंने रास्ते में कुछ गलत भी किया होगा।

ग्राहक लूप (एक बार प्रति फ्रेम, एक बार हर ~ 16.67ms)

सरलीकृत ग्राहक लूप जैसा दिखता है:

  1. स्थानीय इनपुट (WASD) के लिए जाँच करें और उन्हें क्रियाओं (जैसे Type=MoveLeft, Time=132.0902, ID=15) के रूप में पैकेज करें । हम पैक किए गए कार्यों को अंततः उन्हें बाद में भेजने के लिए रखते हैं। इसके अलावा, हम सीधे खेल के स्थानीय भौतिकी सिमुलेशन के लिए वांछित कार्रवाई लागू करते हैं। उदाहरण के लिए, यदि हमारे पास कोई MoveLeftकार्रवाई है, तो हम खिलाड़ी के वेग पर बाईं ओर एक बल लगाते हैं।

  2. कार्रवाई भेजने के लिए जाँच करें। क्लाइंट की बैंडविड्थ को गाली देने से रोकने के लिए, केवल कुछ निश्चित अंतराल (जैसे 30ms) पर पैक किए गए कार्यों को भेजें।

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

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

मैं भौतिकी और अन्य अनुभागों के बारे में कुछ विशिष्ट विवरणों को छोड़ रहा हूं क्योंकि मुझे लगता है कि वे प्रश्न के लिए आवश्यक नहीं हैं, लेकिन मुझे यह बताने में संकोच न करें कि क्या वे प्रश्न के लिए प्रासंगिक होंगे।

सर्वर लूप (प्रत्येक 15ms)

सरलीकृत सर्वर लूप दिखता है:

  1. क्रियाओं को संभालना। ग्राहकों से प्राप्त कार्रवाई पैकेजों की जांच करें और उन्हें सर्वर भौतिकी सिमुलेशन में लागू करें। उदाहरण के लिए, हम 5 MoveLeftक्रियाओं को प्राप्त कर सकते हैं , और हम बल को 5 गुना वेग से लागू करेंगेयह नोट करना महत्वपूर्ण है, एक पूरे एक्शन पैकेज को एक "फ्रेम" पर निष्पादित किया जाता है, ग्राहक के विपरीत जहां यह कार्रवाई होते ही लागू होता है।

  2. गेम लॉजिक को अपडेट करें। हम गेम फ़िज़िक्स, मूविंग प्लेयर्स और फ़िक्सिंग फ़िक्सिंग आदि को अपडेट करते हैं। हम बाद में खिलाड़ियों को भेजे जाने वाले किसी भी महत्वपूर्ण ईवेंट को भी पैकेज करते हैं (उदाहरण के लिए एक खिलाड़ी का स्वास्थ्य गिरा, एक खिलाड़ी की मृत्यु हो गई, आदि)।

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

समस्या

वर्तमान प्रणाली सरल परिस्थितियों में ठीक काम करती है, और मुझे यह देखकर बहुत खुशी हुई कि इसने सरल क्षैतिज आंदोलनों के साथ बहुत ही समान परिणाम दिए (अशुद्धियाँ फ्लोटिंग पॉइंट सटीक त्रुटियों के कारण हैं, मुझे विश्वास है):

सिंक सरल टकराव / आंदोलन के साथ ठीक काम करता है

कृपया प्रोटोटाइप ग्राफिक्स पर ध्यान न दें। सफेद आयत = खिलाड़ी, लाल आयत = बाधाएँ, नीला = पृष्ठभूमि

हालांकि, समय संवेदनशील आंदोलनों, जैसे कि कूदने और एक पृथक बाधा के करीब जाने के बाद मुझे सिंक त्रुटियाँ मिल रही हैं:

सिंक काम नहीं करता है क्योंकि मैं समय-संवेदनशील क्षणों में निर्दिष्ट बाधा के आसपास कूद गया

सिद्धांत रूप में, मैं उम्मीद करूंगा कि दोनों हमेशा एक ही परिणाम के साथ समाप्त होंगे, क्योंकि ग्राहक को उसकी स्थिति को प्रभावित करने वाले कोई बाहरी कारक नहीं हैं। हालांकि, मुझे लगता है कि मैं समस्या को समझता हूं।

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

प्रश्न

यह लंबे समय संदर्भ अंत में मेरे सवाल की ओर जाता है (आप यहां तक पढ़ने के लिए धन्यवाद): यह सर्वर सुधार की आवश्यकता के लिए भी जब वहाँ केवल एक ही खिलाड़ी सर्वर के साथ समकालित है सामान्य है, या मैं समय के प्रति संवेदनशील स्थितियों पर से बचने के desynchronization लिए कुछ तकनीकों का उपयोग करना चाहिए ?

मैंने कुछ संभावित समाधानों के बारे में सोचा है, जिनमें से कुछ के साथ मैं कम सहज हूं:

  1. सर्वर सुधार लागू करें। सीधे शब्दों में मान लें कि यह सामान्य व्यवहार है और त्रुटियों को ठीक करता है क्योंकि वे होते हैं। मैं इसे वैसे भी लागू करना चाहता था, लेकिन मैं सिर्फ यह सुनिश्चित करना चाहता था कि मैंने अभी तक जो किया है वह स्वीकार्य है।

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

  3. एक महान नए विचार के लिए GameDevelopment StackExchange से पूछें जो मेरी सभी समस्याओं को ठीक करेगा।

मैं अभी गेम नेटवर्किंग की दुनिया में शुरुआत कर रहा हूं, इसलिए कृपया ऊपर दिए गए किसी भी कॉन्सेप्ट को सही करने / उसकी आलोचना करने / उसका अपमान करने या विचारों / संसाधनों का अपमान करने के लिए बेझिझक सोचें, जो मुझे वंडरफुल वर्ल्ड ऑफ नेटवर्किंग की मेरी यात्रा में मदद कर सकता है। मुझे क्षमा करें यदि मुझे अपना उत्तर कहीं और मिल सकता है, तो मैं उस पर विफल रहा हूं।

आपके कीमती समय के लिए बहुत-बहुत धन्यवाद।


आपका सर्वर और क्लाइंट विभिन्न दरों पर फ्रेम चलाते हैं। यदि क्लाइंट लगातार फ़्रेमों पर दो क्रियाएं करता है, तो क्या होता है, लेकिन सर्वर उनके बीच एक-फ्रेम अंतर देखता है?
user253751

@immibis ने इस प्रभाव को कम करने के लिए खुद को gafferongames.com/game-physics/fix-your-timestep पर आधारित बताया
जेसी इमोंड

जवाबों:


11

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

क्लाइंट को "I जंप" संदेशों को भेजने के लिए "I जंप से एक्स, वाई टाइम टी" संदेशों को भेजने की आवश्यकता है। सर्वर तब जाँच करता है कि स्थान उस समय के निकट है जो यह सोचता है कि खिलाड़ी उस समय T पर था (जिसे आप अतीत में एक छोटे से समय तक सीमित कर सकते हैं) धोखा देने से बचाने के लिए, फिर ग्राहक से उस स्थिति की छलांग का अनुकरण करें। भेज दिया। सर्वर केवल क्लाइंट को तब ठीक करता है जब वह व्हैक से बाहर होता है (आमतौर पर अंतराल या इस तरह के कारण)।

इस तरह की तकनीक का उपयोग सुधार और प्रक्षेप के साथ संयोजन के रूप में किया जाता है ताकि खेल को स्थानीय ग्राहक पर प्रतिक्रियाशील महसूस किया जा सके और दूरदराज के ग्राहकों के लिए सुचारू रूप से देखा जा सके।


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

आपके खेल के लिए जो भी काम करता है। सरल शुरू करें, इसे केवल उस डिग्री तक जटिल करें जो आपको आवश्यक लगता है। कुछ सर्वर ~max(RTT)अतीत में सर्वर टिक के लिए चारों ओर के प्रकार का एक स्नैपशॉट इतिहास रखते हैं , लेकिन क्या आपको अपने खेल के लिए विशेष रूप से मुझे पता नहीं है। यह शूटर-शैली के खेल के लिए और भी अधिक उपयोगी हो सकता है, जहाँ आप क्लाइंट पर हिट / शॉट डिटेक्शन का कुछ स्तर भी करना चाहते हैं और न केवल यह जानना चाहते हैं कि एक खिलाड़ी 46ms पहले कहाँ था, बल्कि यह भी कि उसका लक्ष्य 46ms पहले और कहाँ था प्लेटफ़ॉर्मिंग को छोड़कर कहां जा रहे हैं।
शॉन मिडिल्डिच

उत्तम। मैं प्रयोग करता हूँ और देखता हूँ कि सबसे अच्छा क्या काम करता है। इसे स्वीकृत उत्तर के रूप में चिह्नित करना, फिर से धन्यवाद!
जेसी इमोंड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.