बहुत सारे क्यूब्स के साथ काम करना। प्रदर्शन सुधारना?


12

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

मैं एक ऐसी परियोजना पर काम कर रहा हूं, जिसमें दुनिया में बड़ी मात्रा में क्यूब्स होते हैं (मैं आपको एक संख्या दूंगा, लेकिन यह उपयोगकर्ता परिभाषित दुनिया है)। मेरा परीक्षण एक (48 x 32 x 48) ब्लॉक के आसपास है।

मूल रूप से ये ब्लॉक अपने आप में कुछ नहीं करते हैं। वे वहीं बसते हैं।

खिलाड़ी इंटरेक्शन की बात आते ही इनका इस्तेमाल शुरू हो जाता है।

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

अब मेरे पास पहले बड़े पैमाने पर अंतराल था, हर ब्लॉक के माध्यम से लूपिंग।

मैंने सभी ब्लॉकों के माध्यम से लूपिंग करके, उस अंतराल को कम करने में कामयाबी हासिल की है, और यह पता लगाया है कि कौन से ब्लॉक चरित्र की एक विशेष सीमा के भीतर हैं, और फिर टकराव का पता लगाने के लिए उन ब्लॉकों के माध्यम से लूपिंग, आदि।

हालाँकि, मैं अभी भी एक निराशाजनक 2fps पर जा रहा हूँ।

क्या किसी के पास कोई अन्य विचार है कि मैं इस अंतराल को कैसे कम कर सकता हूं?

Btw, मैं एक्सएनए (सी #) का उपयोग कर रहा हूं और हां, यह 3 डी है।


आप Minecraft की तरह मतलब है? वह है, स्वर?
द कम्युनिस्ट डक

4
क्या आपने अष्टकवर्ग में देखा है? en.wikipedia.org/wiki/Octree
bummzack

1
क्या आपने अपने खेल की रूपरेखा तैयार करने की कोशिश की है? यह कुछ प्रमुख क्षेत्रों को दिखा सकता है जहां सबसे अधिक समय बिताया जा रहा है। यह वह नहीं हो सकता है जो आप सोचते हैं कि यह है।
deceleratedcaviar

2
प्रत्येक घन के सभी 6 चेहरों को चित्रित करने के बजाय, आप केवल उन चेहरों को आकर्षित कर सकते हैं जो किसी भी चीज़ के संपर्क में नहीं हैं
डेविड एशमोर

1
@ डेविड: हाँ, या वह पहले क्यूब के अनुसार एक ड्रॉ कॉल करना बंद कर सकता था, और फिर बाद में व्यक्तिगत बहुभुज के बारे में चिंता कर सकता था।
ओलहोवस्की

जवाबों:


20

लगता है जैसे आप पेड़ों के बारे में जानना चाह रहे हैं!

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

इससे पहले कि हम क्यों कारणों में जाते हैं, हमारी समस्या के बारे में सोचते हैं। हम एक ऐसे समाधान की तलाश कर रहे हैं, जहाँ तक संभव हो, कम लागत के लिए, हम पास के क्यूब्स की एक सूची पुनः प्राप्त कर सकते हैं जो खिलाड़ी के साथ टकरा सकती है। यह सूची यथासंभव छोटी, फिर भी सटीक होनी चाहिए।

अब इस क्षेत्र को निर्धारित करने के लिए, हमें अपने खिलाड़ी के समन्वय स्थान को घन मानचित्र के समन्वय स्थान पर मैप करने की आवश्यकता है; यही है, हमें खिलाड़ी के फ्लोटिंग पॉइंट पोजीशन को क्यूब्स के बहुआयामी सरणी के असतत इंडेक्स पर मैप करने की आवश्यकता है (उदाहरण नोटेशन हो सकता है world[31][31][31], यानी 64 * 64 * 64 बहुआयामी सरणी के लिए सटीक मध्य)।

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

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

सवाल यह है: हम इसे कैसे लागू करते हैं?

64 * 64 * 64 दुनिया के लिए, इसे 8 * 8 * 8 क्षेत्रों में तोड़ने की कल्पना करें । इसका मतलब यह है कि आपकी दुनिया में, आपके पास अक्ष (एक्स, वाई, जेड) प्रति 8 जोन होंगे। इन क्षेत्रों में से प्रत्येक में 8 क्यूब्स होंगे, इस नए सरलीकृत सूचकांक द्वारा आसानी से पुनर्प्राप्ति योग्य।

यदि आपको अपनी दुनिया के प्रत्येक क्यूब को पुन: व्यवस्थित करने के बजाय, पास के क्यूब्स के एक सेट पर एक ऑपरेशन करने की आवश्यकता है, तो आप मूल रूप से इन जोन पर पुनरावृति कर सकते हैं , मूल 64 * 64 * 64 (264144) से पुनरावृत्तियों की अधिकतम संख्या को तोड़ सकते हैं। सिर्फ 520 (8 * 8 * 8 + 8)।

अब ज़ोन की इस दुनिया से बाहर ज़ूम करें, और ज़ोन को बड़े सुपर-ज़ोन में रखें ; जिसमें प्रत्येक सुपर-जोन में 2 * 2 * 2 नियमित क्षेत्र होते हैं । जैसा कि आपकी दुनिया में वर्तमान में 512 (8 * 8 * 8) क्षेत्र हैं , हम 8 * 8 * 8 ज़ोन को 64 (4 * 4 * 4) सुपर-ज़ोन में 8 ज़ोन को 2 ज़ोन प्रति सुपर-ज़ोन से विभाजित करके तोड़ सकते हैं । ऊपर से एक ही तर्क को लागू करना, यह सुपर-ज़ोन को खोजने के लिए अधिकतम पुनरावृत्तियों को 512 से 8 तक तोड़ देगा ; और फिर कार्यवाही क्षेत्र खोजने के लिए अधिकतम 64(कुल अधिकतम 72)! आप देख सकते हैं कि यह आपको पहले से ही बहुत सारे पुनरावृत्तियों को कैसे बचा रहा है (262144: 72)।

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

नीचे दिए गए चित्र आपको अवधारणा की कल्पना करने में मदद करेंगे। (चित्र विकिपीडिया से: अष्टक ): Octree

अस्वीकरण:

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


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

और मैं अभी भी लगभग 5fps पा रहा हूं :(
जोएल

मैंने अपना उत्तर पुनः दिया, मुझे बताएं कि क्या इससे मदद मिली।
डेक्लेरेटेडकविअर

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

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

13

मैं बक्से की बड़ी मात्रा के माध्यम से है कि बार-बार दोहराना में डेनियल जवाब से सहमत हैं, है सबसे संभावित कारण, और spacial विभाजन का उपयोग करके आप एक बहुत ऊपर खेल गति सकता है कि - लेकिन समस्या सकता भी कहीं और हो, और आप अपना समय बर्बाद कर किया जा सकता है ।

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

आपके कोड को प्रोफाइल करने के बहुत सारे तरीके हैं, आप अपने स्वयं के प्रदर्शन विश्लेषण वर्ग (जो स्टॉपवॉच वर्ग (MSDN) का उपयोग कर सकते हैं ) ) को रोल कर सकते हैं , या आप PIX का उपयोग करके सामान्य विचार प्राप्त कर सकते हैं कि CPU / GPU कितना व्यस्त है। ।

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


2
+1, पूरी तरह से सहमत हैं। आपको एल्गोरिदम में नहीं देखना चाहिए, आपको अपना कोड प्रोफाइलिंग करना चाहिए। मेरा अनुमान है कि इसका इस तथ्य से कोई लेना-देना नहीं है कि आप ब्लॉकों से गुजर रहे हैं (यह ऐसा नहीं है), यह वही है जो आप प्रत्येक ब्लॉक के लिए कर रहे हैं। अंतत: हाँ, आपको पाशविक बल की तुलना में एक बेहतर विधि की आवश्यकता है, लेकिन यदि आप 48x32x48 क्यूब्स पर एक सरल पुनरावृत्ति को संभाल नहीं सकते हैं, तो आपको प्रत्येक क्यूब के साथ क्या कर रहे हैं, इस पर पुनर्विचार करने की आवश्यकता है, न कि आप कैसे पाशन कर रहे हैं।
टिम होल्ट

4
@ टिम: जब तक उसका खिलाड़ी 48x32x48 के स्थान पर कब्जा करने के लिए पर्याप्त नहीं है, तब तक उसे कई क्यूब्स के पास कहीं से भी पुनरावृत्त नहीं होना चाहिए। यदि वह प्रति फ्रेम 73000 क्यूब्स के माध्यम से पुनरावृत्ति कर रहा है, तो मैं आपको बिना किसी प्रोफाइलिंग के बता सकता हूं, कि उसे ठीक करने के लिए इसके लायक है, अगर कोई अन्य कारण नहीं है तो सीखने के अलावा कि दसियों हज़ार से अधिक पुनरावृत्तियों से कैसे बचें। जरूरी हैं। यह वह नहीं है जिसे मैं माइक्रो या प्रीमेच्योर ऑप्टिमाइज़ेशन कहूंगा।
ओलहोवस्की

मेरा खिलाड़ी 1 क्यूब के आकार से कम है, हालाँकि यह किसी भी स्तर पर बड़ा हो सकता है (लेकिन ज्यादा नहीं)
जोएल

Randomman159: फिर आपको केवल टकराव खोजने के लिए उसके आसपास के 27 क्यूब्स के खिलाफ परीक्षण करना होगा। मेरा जवाब देखिए।
ओल्होव्स्की

6

यदि आपका खिलाड़ी क्यूब्स के आकार के सापेक्ष बड़ा है, तो आप संभवतः एक ऑक्ट्री या अन्य स्थानिक विभाजन संरचना चाहते हैं, जैसा कि अन्य ने सुझाव दिया है।

हालांकि, यदि आपका खिलाड़ी क्यूब्स के आकार के सापेक्ष छोटा है, तो संभवतः क्यूब्स के साथ टकराव का पता लगाने का सबसे तेज़ तरीका खिलाड़ी के आसपास के क्षेत्र की एक सरल रेखीय खोज करना है।

चूंकि आपका खिलाड़ी 1 क्यूब से छोटा है, तो आपको केवल पड़ोसी 27 क्यूब्स के खिलाफ टक्कर के लिए परीक्षण करना होगा।

यह मानता है कि आप क्यूब को एक सरणी में संग्रहीत करते हैं जिसे आप प्रत्येक क्यूब के लिए सरणी में एक स्लॉट के साथ अनुक्रमित कर सकते हैं।

जैसा कि अन्य ने बताया है, आपको अपने कोड को यह देखने के लिए प्रोफाइल करने की आवश्यकता है कि वास्तव में क्या आपको धीमा कर रहा है।

अगर मुझे अनुमान लगाना था, तो मैं कहूंगा कि आप शायद हर घन के लिए एक ड्रॉ कॉल कर रहे हैं, जो अब तक आपकी अड़चन होगी। इसे ठीक करने के लिए, आपको ज्यामिति इंस्टेंसिंग पर ध्यान देना चाहिए।


या आपके पास एक 'बाउंडिंग बॉक्स' हो सकता है जो खिलाड़ी को घेरता है, और फिर आप बस यह जांचते हैं कि यह किन वस्तुओं से टकरा रहा है, यह निर्धारित करने के लिए कि खिलाड़ी को किन चीजों से टकरा जाना चाहिए। एक अच्छा भौतिकी इंजन आपके लिए सभी अनुकूलन करने में सक्षम होगा; यह केवल 'ब्लॉक' से अधिक के साथ टकराने की अनुमति देगा।
डेक्लेरेटेडकविअर

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

1

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

यह स्पष्ट है कि Minecraft इस पर कुछ करता है - मैंने एक गैर-भरी हुई ठोक को एक बार मारा, जिसने मुझे दुनिया में एक दृश्य दिया - मैं ठोस जमीन के माध्यम से सही देख सकता था, जो सब दिखा रहा था वह खुली जगह थी (दूर की तरफ) उन्हें एक उजागर सतह थी और इसलिए प्रदान किया गया।)


-1

मैं अपने voxel इंजन के साथ उस मुद्दे था।

समाधान: (ऑक्टर्स से बहुत सरल) सभी ब्लॉकों के माध्यम से लूपिंग के बजाय, ब्लॉक सरणी में ब्लॉक की स्थिति निर्धारित करने के लिए बस एक समीकरण का उपयोग करें।

BlockIndex = (x * WorldWidth * WorldHeight) + (z * WorldHeight) + y;

यदि आप देखना चाहते हैं कि क्या कोई ब्लॉक मौजूद है:

Blocks[BlockIndex].Type > -1;

या हालांकि आप निर्धारित करते हैं कि ब्लॉक मौजूद है।


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