आरटीएस गेम प्रोटोकॉल


18

मैं एक मल्टी प्लेयर RTS गेम के बारे में सोच रहा हूं। जिस भाग को मैं प्राप्त नहीं कर सकता, वह इकाई गति को समकालिक रखता है। यदि मैं XY को स्पॉट करने के लिए यूनिट ए को स्थानांतरित करता हूं, तो मुझे उस सर्वर पर वापस संचार करना होगा जो अन्य क्लाइंट से संबंधित है।

मैं उत्सुक हूं कि संचार कैसा दिखेगा। क्या आप सिर्फ उस सर्वर से संवाद करेंगे जो मैं JZ से इकाई A को XY में स्थानांतरित कर रहा हूं? हो सकता है कि आपको इसके बजाय समन्वय द्वारा आंदोलन के समन्वय की आवश्यकता हो? एक ग्राहक से दूसरे में इकाइयों की आवाजाही को संवाद करने के लिए सबसे कुशल कार्यप्रणाली क्या है?

संपादित करें

यह स्टैकओवरफ्लो से एक रीपोस्टेड प्रश्न है । मैंने पाया कि यह साइट शायद सवाल के लिए एक बेहतर जगह थी।

उस पोस्ट से बेहतर उत्तरों में से एक:

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


2
जवाब वास्तव में निर्भर करता है कि आप किस विधि का उपयोग करना चाहते हैं। क्लाइंट - क्लाइंट या क्लाइंट - सर्वर। सर्वर के लिए क्लाइंट आसान है, लेकिन यह एक आवश्यकता है trustable सर्वर
सीमेंट Kalyoncu

जवाबों:


25

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

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

नकारात्मक पक्ष यह है कि हर खिलाड़ी सबसे धीमे खिलाड़ी के रूप में धीमा है - अगर कोई भी बाहर भेजने में पीछे पड़ता है, तो सभी को धीमा होना पड़ता है और उसे पकड़ने के लिए इंतजार करना पड़ता है (Starcraft 2 में, यह "XXX खेल को धीमा कर रहा है) " संवाद)।


वास्तव में, एक और चीज है जो आमतौर पर की जाती है: सर्वर को पूरी तरह से समाप्त करना । क्या हर क्लाइंट अपने कमांड को हर दूसरे क्लाइंट के पास भेजता है। यह अंतराल कम कर देता है (आपके बजाय किसी कमांड से -> सर्वर -> प्रतिद्वंद्वी से, यह सिर्फ आप से -> प्रतिद्वंद्वी से जाता है) और कोडिंग को आसान बनाता है, क्योंकि अब आपको एक अलग सर्वर को कोड करने की आवश्यकता नहीं है। इस तरह की वास्तुकला को पीयर-टू-पीयर (पी 2 पी) कहा जाता है ।

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


यह सेटअप (केवल पी 2 पी का उपयोग करके आदेश भेजना) है कि स्टारकास्ट, सी एंड सी, और एओई काम सहित आरटीएस का सबसे अधिक उपयोग कैसे किया जाता है, और एओई संभवतः 28.8kbps कनेक्शन पर 1500 इकाइयों का समर्थन कर सकता है ।

(AoE में नेटवर्किंग की छवि)

पी 2 पी आरटीएस लिखने के लिए यहां कुछ और सुझाव दिए गए हैं:

  • स्पष्ट कारणों के लिए, यह सेटअप केवल तभी काम कर सकता है जब आपका गेम निश्चित-चरण समय का उपयोग करता है - आप नहीं चाहते कि गणना के परिणाम फ्रैमरेट पर निर्भर हों! फिक्स्ड-स्टेप ज्यादातर चीजों के लिए काम करना आसान है, इसलिए यह समस्या नहीं होनी चाहिए।
  • इसके लिए कार्य करने के लिए, प्रत्येक आदेश के परिणाम पूरी तरह से निर्धारक होना चाहिए ।
    • यह आमतौर पर बहुत आसान है यदि आप अपने आप को एक सिस्टम (जैसे 32-बिट विंडोज) तक सीमित रखते हैं और सभी ग्राहकों को एक ही निष्पादन योग्य का उपयोग करने के लिए मजबूर करते हैं: सुनिश्चित करें कि किसी भी यादृच्छिक-संख्या जनरेटर के पास एक ही बीज है और हमेशा उसी क्रम में कहा जाता है; अनियंत्रित संग्रह पर पुनरावृति होने पर अत्यंत सावधान रहें ; आदि।
    • यदि आप गेम को विभिन्न प्लेटफार्मों पर खेलने योग्य बनाने की योजना बना रहे हैं, या (जैसा कि अक्सर लिनक्स के साथ होता है) ग्राहकों को कोड को स्वयं संकलित करने की अनुमति देता है, तो यह बेहद मुश्किल है। न केवल अलग-अलग सिस्टम पुस्तकालयों rand(), cos()आदि के विभिन्न कार्यान्वयन का उपयोग करने के लिए बहुत अधिक गारंटी दी जाती है , बल्कि बहुत सारे फ़्लोटिंग पॉइंट गणित प्रश्न से बाहर है ( यहां , यहां और यहां देखें ) ! उस स्थिति में, आप क्लाइंट-सर्वर का उपयोग करके बेहतर हो सकते हैं।
  • आप desync कीड़े (जो, मुझे विश्वास है, तो आप पता लगाने के लिए एक समय में सभी इकाई पदों हर बाहर भेजने के लिए एक बार चाहते करने जा रहे हैं, कम से कम, जबकि डीबगिंग जाएगा है)। चाहे आप इसे अंतिम गेम में रखते हों या नहीं - मैं प्रयास-हैकिंग का पता लगाने के लिए कम से कम कुछ इकाइयों (या किसी प्रकार के चेकसम का उपयोग) को सिंक करूंगा।

अच्छी पोस्ट। जोड़ने के लिए छोटी सी बात, यहां तक ​​कि समान कंपाइलर ऑप्टिमाइज़, डिबग / रिलीज़ और अन्य झंडे परिणाम को बदल सकते हैं। सावधान रहे!
पीटर Peterलस्टेड

14

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

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

सर्वर एक 'टिक' नंबर भेजता है जिस पर कमांड को निष्पादित करने के लिए, जो 'चालू' टिक के आगे कुछ टिक है। इस तरह सभी मशीनों पर एक ही 'टिक' पर सभी कमांड निष्पादित किए जा सकते हैं।

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

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

जैसे कि संदेश क्या दिख सकते हैं। मैं अल्ट्रा दक्षता से चिंतित नहीं था क्योंकि यह मेरा पहला नेटवर्क गेम था। मैंने आदेशों को तार के रूप में पारित किया। आदेशों को इस तरह प्रारूपित किया जाएगा:"<player_id>:<command>:<parameters>"

एक आकस्मिक उदाहरण के लिए, एक चाल कमांड इस तरह दिख सकता है "3:move:522:100:200":। इसका मतलब है कि प्लेयर ( , ) 3को moveयूनिट करना चाहता है । 522100200

सर्वर सभी क्लाइंट्स को कमांड भेजता है, जिसमें इसे भेजने वाला भी शामिल है, जैसे एक टिक नंबर संलग्न किया गया है "153238:3:move:522:100:200":।

तब क्लाइंट सभी इस कमांड को निष्पादित करेंगे जब टिक 153238 निष्पादित किया जाता है।


मैंने प्रश्न के लिए थोड़ा और जानकारी जोड़ी। एसओ के उत्तर से लगता है कि आपने जो कहा था, उसके विपरीत है और मैं महीन विवरणों पर चर्चा करना पसंद करूंगा।
डार्थग्रे g

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