एक नेटवर्क पर एक डेटा संरचना को सिंक्रनाइज़ कैसे रखें?


12

प्रसंग

जिस खेल में मैं काम कर रहा हूँ (एक बिंदु का एक प्रकार और ग्राफिक एडवेंचर पर क्लिक करें), खेल की दुनिया में होने वाली हर चीज को एक एक्शन मैनेजर द्वारा नियंत्रित किया जाता है जिसे थोड़ा सा संरचित किया जाता है:

यहाँ छवि विवरण दर्ज करें

उदाहरण के लिए अगर किसी वस्तु की जांच करने का परिणाम चरित्र को नमस्कार कहना चाहिए, तो थोड़ा चलें और फिर बैठें, मैं बस निम्नलिखित कोड को लिखता हूं:

var actionGroup = actionManager.CreateGroup();
actionGroup.Add(new TalkAction("Guybrush", "Hello there!");
actionGroup.Add(new WalkAction("Guybrush", new Vector2(300, 300));
actionGroup.Add(new SetAnimationAction("Guybrush", "Sit"));

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

संकट

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

var actionManager = new List<List<string>>();

मुझे उपरोक्त डेटा संरचना की सामग्री को सभी खिलाड़ियों के बीच समन्वयित रखने के लिए कैसे आगे बढ़ना चाहिए?

मुख्य प्रश्न के अलावा, मुझे इससे संबंधित कुछ अन्य चिंताएँ भी हैं (अर्थात उपरोक्त समान समस्या के सभी संभावित निहितार्थ):

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

5
Obligatory "यह पहली बार पढ़ें" लिंक gafferongames.com/networking-for-game-programmers जो कुछ कोड होने के बावजूद बहुत तकनीकी नहीं है, लेकिन यह चिंताजनक है और आपके विकल्पों को काफी अच्छी तरह से समझाता है। साथ ही यह आपको बाकी सभी के साथ बराबरी पर रखेगा जो उस लिंक को पढ़ते हैं और वह एक खुशहाल जगह है।
पैट्रिक ह्यूजेस

@PatrickHughes लिंक के लिए धन्यवाद! मैं निश्चित रूप से यह सब पढ़ रहा हूँ।
डेविड गाविया

कुछ पैकेज हैं जो आपके लिए इस तरह की चीज़ का प्रबंधन करते हैं। मुझे नहीं पता कि यह कितना कुशल या तेज़ है, लेकिन NowJS ( nowjs.com ) एक दिलचस्प उदाहरण है। डेवलपर्स के दृष्टिकोण से, आपने बस क्लाइंट और सर्वर के बीच डेटा संरचनाएं साझा की हैं। एक को बदलो, दूसरे को बदलो।
टिम होल्ट

जवाबों:


9

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

आपके पास इस मामले में तीन विकल्प हैं, जिनमें से दो का आप पहले ही उल्लेख कर चुके हैं। आप किस विकल्प को चुनते हैं, यह कई कारकों पर निर्भर करता है कि केवल आप ही सबसे अच्छे न्यायाधीश हो सकते हैं:

1: क्लाइंट क्रियाओं के समूह को सीधे जोड़ता है और फिर उन्हें सर्वर पर भेजता है। सर्वर इसे बिना किसी जांच के स्वीकार करता है

* इस दृष्टिकोण के लाभ यह है कि जहां तक ​​ग्राहक का संबंध है, उनकी अपनी कार्रवाई उन्हें नेटवर्क देरी से स्वतंत्र एक त्वरित प्रतिक्रिया देती है। नुकसान यह है कि क्लाइंट के संदेश सर्वर द्वारा तथ्य के रूप में स्वीकार किए जाते हैं (जो वे नहीं हो सकते हैं) *

2: क्लाइंट सर्वर के लिए एक अनुरोध भेजता है, जो बदले में अनुरोध को उत्पन्न करने वाले क्लाइंट सहित सभी के लिए अनुरोध प्रसारित करता है।

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

3: क्लाइंट क्रियाओं का समूह बनाता है, उन्हें सीधे जोड़ता है और फिर उन्हें सर्वर पर भेजता है। सर्वर अनुरोध को संसाधित करता है, यह सुनिश्चित करने के लिए कि वे अवैध नहीं हैं, और फिर क्लाइंट सहित सभी खिलाड़ियों के लिए इस कदम को प्रसारित करता है, कार्रवाई पर अपनी जांच चलाता है।

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

पैकेट घाटे और पसंद के बारे में क्या? खेल नियतात्मक है, लेकिन मैं सोच रहा हूं कि एक ग्राहक में निष्पादित कार्यों के अनुक्रम में कोई विसंगति दुनिया के असंगत राज्यों को जन्म दे सकती है। मैं उस तरह की समस्या से कैसे बचाव कर सकता हूं?

पैकेट नुकसान और चरम अंतराल को ठीक करने के लिए एक कठिन समस्या है । विभिन्न प्रकार के समाधान (उनमें से कोई भी सही) खेल के प्रकार (उदाहरण के लिए मृत-गणना) के आधार पर समस्या से निपटने के लिए कार्यरत हैं। मुझे लगता है कि आप खेल भौतिकी को सिंक्रनाइज़ करने के लिए नहीं है।

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

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

क्या होगा अगर मैं एक ही बार में बहुत सारी कार्रवाइयाँ जोड़ दूं, तो क्या इससे कनेक्शन की समस्या नहीं होगी? किसी भी तरह से कम करने के लिए?

पहले स्पष्ट सामान। तार या क्रमबद्ध वस्तुएं कभी न भेजें। जितनी जल्दी गेम अपडेट हो रहा है उतनी तेजी से मैसेज न भेजें। उन्हें विखंडू में भेजें (जैसे 10 बार एक सेकंड)। त्रुटि होगी (विशेष रूप से राउंडिंग त्रुटि) जिसे सर्वर / क्लाइंट को एक बार में त्रुटियों को ठीक करने की आवश्यकता होगी (इसलिए हर सेकंड, सर्वर सब कुछ भेजता है [सब कुछ = सभी डेटा) जो आपके गेम में चीजों को सही रखने के लिए महत्वपूर्ण है राज्य] जिसे ग्राहक तब अपने राज्य को सही करने के लिए स्नैप और / या खाते में लेता है)।EDIT: मेरे एक सहकर्मी ने उल्लेख किया कि यदि आप यूडीपी का उपयोग कर रहे हैं [जो आपको चाहिए, यदि आपके पास बहुत अधिक डेटा है] तो कोई नेटवर्क ऑर्डर नहीं है। 10 से अधिक पैकेट भेजने से दूसरे क्रम से आने वाले पैकेट के परिवर्तन बढ़ जाते हैं। मैं देखूंगा कि क्या मैं उस दावे का हवाला दे सकता हूं। ऑर्डर पैकेट के बाहर के रूप में, आप या तो उन्हें छोड़ सकते हैं या इसे अपने सिस्टम के संदेश / चाल कतार में जोड़ सकते हैं जो वर्तमान स्थिति को ठीक करने के लिए अतीत में परिवर्तन को संभालने के लिए डिज़ाइन किया गया है

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

आपकी मैसेजिंग प्रणाली आपको आने वाले मैसेज से आसानी से मूव्स निकालने की अनुमति देने के लिए बहुत सारी एनमों का उपयोग करने की संभावना बनाएगी (मैं RakNet पर एक नज़र रखने का सुझाव दूंगा और इसमें उदाहरणों के साथ अगर आपको समझ में नहीं आया कि मेरा यहाँ क्या मतलब है)।

मुझे यकीन है कि आप पहले से ही जानते हैं कि आप उन समस्याओं को ठीक नहीं कर सकते जो हाईट लेटेंसी और पैकेट लॉस के साथ उत्पन्न होती हैं, लेकिन आप इसके प्रभाव को कम स्पष्ट कर सकते हैं। सौभाग्य!

EDIT: ऊपर दिए गए लिंक के साथ पैट्रिक ह्यूजेस की टिप्पणी इस उत्तर को अपूर्ण और विशिष्ट रूप से ओपी के प्रश्न के लिए सबसे अच्छा बताती है। मैं इसके बजाय जुड़े हुए विषयों को पढ़ने का सुझाव दूंगा


विस्तृत प्रतिक्रिया के लिए बहुत बहुत धन्यवाद, यह बहुत ज्यादा मेरी चिंताओं को शामिल करता है। जहाँ आप कहते हैं उस भाग के संबंध में सिर्फ एक प्रश्न so every second, the server sends everything ... which the client then snaps to। क्या मैं एक बार में इस तरह की बड़ी जानकारी भेज सकता हूं? एक उचित अधिकतम आकार क्या है?
डेविड गौविया

एक उचित अधिकतम एक संख्या होगी जो लैग का परिचय नहीं देती है:) ... मुझे पता है कि आप उस उत्तर की तलाश नहीं कर रहे थे, लेकिन मैं एक नंबर नहीं डालना चाहता क्योंकि मैं आपके गेम से परिचित नहीं हूं।
समरसा

इसके अलावा, कोई कठिन नियम नहीं है कि आपको एक बड़ा हिस्सा भेजना चाहिए, मैंने सिर्फ एक उदाहरण के रूप में दिया है।
समरसता

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

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