MMO में सर्वर के साथ कम ट्रैफ़िक क्लाइंट सिंक्रनाइज़ेशन


22

मैं ऐसे MMO को लागू कर रहा हूं जहां खिलाड़ी अपने स्टारशिप पर अंतरिक्ष में उड़ता है और इसे तीर कुंजी से नियंत्रित करता है और अन्य खिलाड़ियों के साथ सहयोग करता है।

मैं इसे लागू करना चाहता हूं ताकि खिलाड़ी अपने जहाज को रॉकेट या किसी और चीज से चकमा दे सके, इसलिए मैं सर्वर गेम के रूप में एक ही विश्व अनुकरणीय एल्गोरिदम का उपयोग करके क्लाइंट गेम पर पूरे खेल राज्य की भविष्यवाणी करने की कोशिश कर रहा हूं। यह गेम वर्ल्ड C # पर लिखा गया है और इसे क्लाइंट के अंदर सीधे (इसे Unity3D पर लिखा गया है) और CLR के माध्यम से C ++ सर्वर (लिनक्स के तहत) पर लिखा जाएगा। यूडीपी के माध्यम से कनेक्शन।

समस्या यह है कि कैसे बनाए रखा जाए, उदाहरण के लिए, एकल मानचित्र के भीतर 1000 खिलाड़ी (अन्य सभी खेल वस्तुओं, भीड़ को छोड़कर ...): आइए हम आपको बताएं:

  • प्रति सेकंड 50 बार ग्राहकों के साथ सर्वर को सिंक्रनाइज़ करें
  • प्रत्येक ग्राहक को उस गेम ऑब्जेक्ट (और खिलाड़ी) को भेजें जिसे वह देखने में सक्षम है (कुछ त्रिज्या के भीतर)
  • प्रत्येक खिलाड़ी को अपने विचार त्रिज्या के भीतर 100 वस्तुओं को भेजना होगा
  • प्रति गेम ऑब्जेक्ट औसतन 50 बाइट भेजना चाहिए (यह id, x, y coords, रोटेशन, राज्य ...)

इसलिए, इस तरह के नेटवर्क बैंडविड्थ की आवश्यकता होगी: 1000 (क्लाइंट) * 50 (प्रति सेकंड बार) * 100 (प्रत्येक खिलाड़ी को भेजने के लिए ऑब्जेक्ट) * 50 (प्रति ऑब्जेक्ट बाइट्स) = 250 000 000 प्रति सेकंड बाइट्स! यह नामुमकिन है!

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

वैसे भी, इस तरह के खेलों को सामान्य तरीके से कैसे प्रोग्राम किया जाता है? धन्यवाद।


1
मैं ऑब्जेक्ट्स (दुनिया की स्थिति, वर्तमान स्थिति (जो एक बाइट है) और इतने पर) के बारे में सिर्फ तार्किक जानकारी भेजता हूं - कोई ग्राफिक्स नहीं।
स्लाव

1
@ शाल: अच्छा! वह सब थोड़ा सा बदलाव मेरे ASM प्रोग्रामिंग दिनों की याद दिलाता है।
1922 में Randolf रिचर्डसन

1
"आज के दिन" क्यों नहीं? :) जब मैं AS3, Java, Lua, C # पर लिखता हूं और ऐसे खराब प्रदर्शन का सामना करता हूं तो मुझे C ++ की याद आती है और ASM के बारे में याद आता है।
स्लाव

1
@Slav: हेह, मैंने हाल ही में बहुत ASM नहीं किया है। मेरे लिए ज्यादातर चीजें इन दिनों जावा और पर्ल (mod_perl2 ज्यादातर) में हैं, लेकिन मैं इन भाषाओं का भी आनंद लेता हूं।
रंडोल्फ रिचर्डसन

2
@Slav, आपने लिखा: "जब मैं AS3, जावा, लुआ, C # पर लिखता हूं और ऐसे खराब प्रदर्शन का सामना करता हूं तो मुझे C ++ की याद आती है और ASM के बारे में याद आता है"। आपको सीखना चाहिए कि लुआ और सी # का सही उपयोग कैसे करें, हो सकता है कि आपको प्रदर्शन कम मिल जाए। इसके अलावा, (कथित रूप से) सबसे तेजी से स्क्रिप्टिंग भाषा के बारे में शिकायत करना सबसे अच्छा विलक्षण है ... क्या यह वास्तविक मानव जीनोम विश्लेषण के बारे में एक खेल है?
रैन

जवाबों:


20

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

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

फिर, अनावश्यक डेटा की मात्रा को कम करने के लिए आप उन्हें BitVectors या howevery का भारी उपयोग कर सकते हैं! उदाहरण: आप केवल एक बाइट (0 से 1 या -1 से 1 की सीमा में) का उपयोग करके एक फ्लोट लिखने की कोशिश कर सकते हैं, इसलिए आपके पास केवल 256 या 128 विभिन्न मूल्य हैं। लेकिन खिलाड़ी प्रक्षेपों के लिए धन्यवाद किसी भी झटकेदार आंदोलनों को नोटिस नहीं करेगा।

डेटा को संपीड़ित करने के तरीके पर LidgrenLibrary के उदाहरण के लिए इसे देखें: http://code.google.com/p/lidgren-network-gen3/wiki/Optimization

अगला: खिलाड़ियों के दृश्य त्रिज्या को कम करने की कोशिश करें क्योंकि वे चलते हैं, और केवल उस समय में महत्वपूर्ण जानकारी संचारित करते हैं। फिर जब वे रोकते हैं तो फिर से अपना दायरा बढ़ाते हैं। आप "रेंज" में दिखने वाली वस्तुओं को देखने के ओवरहेड को कम करने के लिए एक स्थानिक हैशिंग सिस्टम या एक बीपी ट्री का उपयोग कर सकते हैं। यह विषय के लिए एक अच्छा पढ़ा गया है: http://en.wikipedia.org/wiki/Collision_detection

डेटा को भी संकुचित करें YourSELF केवल आप डेटा संरचना और डेटा में अस्थायी सामंजस्य (जो शोषण किया जा सकता है और होना चाहिए) के बारे में जानते हैं। एक सामान्य एल्गोरिथ्म जैसे Bzip2, Deflate, जो भी हो, का उपयोग किया जाना चाहिए, लेकिन केवल संपीड़न के अंतिम चरण के रूप में!

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

EDIT (टिप्पणी के कारण):

प्रत्येक खिलाड़ी के लिए प्रति सेकंड औसत बिट संख्या को कम करने के लिए अतिरिक्त तरीके:

  1. आपने लिखा है कि आप "वस्तु नहीं बदली" भेजते हैं। ऐसा करने का कोई कारण नहीं है। यदि आप पैकेट के नुकसान के बारे में चिंता करते हैं (और इसके कारण आपके सिमुलेशन को सिंक से बाहर कर रहे हैं) निम्न पर विचार करें: प्रत्येक निश्चित समय पर (उदाहरण के लिए 100, 200, 300, 400 ...) सिमुलेशन स्थिति हैश और सर्वर पर भेजें। । सर्वर पुष्टि करता है या सभी डेटा का पूरा स्नैपशॉट वापस भेजता है।

  2. रॉकेट या यहां तक ​​कि खिलाड़ियों जैसी चीजों के लिए आप न केवल प्रक्षेप को नियोजित कर सकते हैं, बल्कि अनुकरण को अधिक यथार्थवादी बनाने के लिए भी एक्सट्रपलेशन कर सकते हैं। उदाहरण 'रॉकेट': "अभी स्थिति x पर है" जैसे संदेशों के साथ अद्यतन करने के बजाय, बस एक संदेश भेजें जिसमें निम्न में से एक बार हो: "रॉकेट स्पॉनड: स्थिति (वेक्टर), समय (जिस स्टेप पर स्टेप रॉकेट को स्थानांतरित किया गया था), वेग (> वेक्टर)"। इसलिए आपको रोटेशन को शामिल करने की भी आवश्यकता नहीं है क्योंकि टिप हमेशा "वेग" दिशा में होगी।

  3. एक संदेश में कई आदेशों को मिलाएं और 16-20bytes से छोटे संदेशों को कभी न भेजें क्योंकि udp हेडर स्वयं संदेश से बड़ा होगा। इसके अलावा अपने प्रोटोकॉल के MTU से बड़े पैकेज न भेजें क्योंकि विखंडन संचरण की गति को धीमा कर देगा।


ओह, कुछ वस्तुओं को दूसरों की तुलना में अधिक बार अपडेट करना अच्छा लगता है, P2P का उपयोग करें, फ्लोटिंग पॉइंट सटीकता को कम करें, बस परिवर्तन भेजें (जो मेरे लिए तुच्छ नहीं है क्योंकि मेरा उद्देश्य समय-समय पर वस्तुओं को सिंक करना है लेकिन "ऑब्जेक्ट नहीं बदला गया") जानकारी है भी)। इन सभी संशोधनों के साथ पूरी तस्वीर अधिक यथार्थवादी लगती है!
स्लाव

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

5

यहाँ दो दृष्टिकोण हैं:

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

ग्राहक को दो या तीन एक साथ सिमुलेशन चलाने होंगे।
1: अगले स्टेप के लिए जब भी डेटा गुम होता है तो उसे हटा दें।
2: अनुमान डेटा का उपयोग करना जारी रखें और रेंडरिंग के लिए उपयोग की गई स्थिति प्रदान करें। 3: जब भी कोई 1 पड़ाव नहीं आता है, तो यह अनुकरण नंबर 1 की स्थिति को कॉपी करता है, वर्तमान समय तक पकड़ता है और कोई 2 नहीं लेता है, जो तब गिरा दिया जाता है।

यदि पकड़ काफी तेज है तो आप 2 और 3 नंबर के बीच अंतर छोड़ सकते हैं और पुराने डेटा को तुरंत छोड़ सकते हैं।

दूसरा:
नियतात्मक भौतिकी का उपयोग न करें, ऊपर के समान करें, लेकिन हर कुछ सेकंड में एक बार "पूर्ण फ़्रेम" भेजें। आप आसानी से गोलियों की तरह अस्थायी सामान को स्थानांतरित करने से पूरी तरह से बाहर निकल सकते हैं।

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

और गणित करने के लिए +1, बहुत से लोग सरल संसाधन उपयोग अनुमान लगाने में विफल होते हैं।


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

3
इसका अर्थ है पूर्णांक और निश्चित समय कदम। सैद्धांतिक रूप से आप फ्लोट पॉइंट को व्यवहार करने के लिए मॉक कर सकते हैं, लेकिन पूर्णांक का उपयोग करना सरल है। आपको लापता मिसाइल के उदाहरण के साथ एक बिंदु मिला है, यदि आप गैर-नियतात्मक भौतिकी का उपयोग करते हैं तो संभवतः यह सबसे अच्छा है कि सर्वर को पूरी तरह से मौत को संभालने दें, और मृत्यु / विनाश के मामलों को तेजी से संचारित करें।
आआआआआआआआआआ आआआआ

5

पहले कुछ सवाल।

क्या 'रॉकेट या कुछ और' बुद्धिमान या गूंगा हैं? यदि वे गूंगा हो तो आपको अपनी आग, मूल, और सदिश का पथप्रदर्शन करना चाहिए। यदि वे बुद्धिमान हैं तो वे कितने बुद्धिमान हैं? क्या आप आग के समय गणना कर सकते हैं कि वे हिट या मिस करने जा रहे हैं? यदि ऐसा है तो आप क्लाइंट पर पूरे पथ का अनुकरण कर सकते हैं। ("T13 पर मिसाइल जहाज को मार डालेगी क्योंकि नाटक चकमा देने वाला रोल खो गया / शूटर ने एक महत्वपूर्ण स्कोर बनाया।"

सामान्य तौर पर हालांकि इसके बहुत अधिक कारण नहीं हैं: ए) की घड़ी की दर 50 हर्ट्ज है, (अधिकांश निशानेबाज 15-20 के साथ दूर हो जाते हैं और पैराग्राफ इससे कम हैं।) बी) हर फ्रेम में पूर्ण राज्य भेजते हैं। (क्या अंतरिक्ष में किसी मिसाइल का घूमना बिल्कुल मायने रखता है? या क्या आप यह मान सकते हैं कि यह 'मोर्चा' सदिश यात्रा के दौरान उन्मुख है?)

भविष्यवाणी और प्रक्षेप के साथ समय बिताएं, और आप अपने बैंडविड्थ प्लमेट देखेंगे। एक परियोजना जिस पर मैंने काम किया था उसकी अद्यतन दर 10 हर्ट्ज थी, और मुझे लगता है कि 14 बाइट्स का एक वस्तु राज्य प्रतिनिधित्व था। (सब कुछ आप कर सकते हैं संपीड़ित करें। मेरा मानना ​​है कि हमने x विमान के चारों ओर रोटेशन को परिभाषित करने के लिए 6 बिट्स का उपयोग किया और फिर उस विमान के ऊपर / नीचे एक झुकाव के लिए एक और 6 बिट्स, यह एक वास्तविक घूर्णी मैट्रिक्स / क्वाटर्नियन भेजने से अप्रभेद्य दिखाई दिया।)

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

सामान्य विचार क्लाइंट पर एक आदर्श सिमुलेशन बनाने के लिए नहीं है, यह असंभव है, यह विचार एक मजेदार गेम बनाने के लिए है जहां खिलाड़ी ध्यान नहीं देंगे कि यह एक आदर्श सिमुलेशन नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.