मैं एक Voxel / Minecraft प्रकार के खेल की गति प्रदान करने में सुधार कैसे कर सकता हूं?


35

मैं अपने स्वयं के Minecraft का क्लोन लिख रहा हूं (जावा में भी लिखा है)। यह अभी महान काम करता है। 40 मीटर की दूरी देखने के साथ मैं अपने मैकबुक प्रो 8,1 पर 60 एफपीएस आसानी से मार सकता हूं। (इंटेल i5 + इंटेल एचडी ग्राफिक्स 3000)। लेकिन अगर मैं देखने की दूरी 70 मीटर रखूं, तो मैं केवल 15-25 एफपीएस तक पहुंच सकता हूं। वास्तविक Minecraft में, मैं एक समस्या के बिना दूर (= 256 मीटर) पर देखने के विघटन को लगा सकता हूं। तो मेरा सवाल यह है कि मुझे अपने खेल को बेहतर बनाने के लिए क्या करना चाहिए?

मेरे द्वारा लागू किए गए अनुकूलन:

  • केवल स्थानीय विखंडू को स्मृति में रखें (खिलाड़ी की देखने की दूरी के आधार पर)
  • Frustum culling (पहले विखंडू पर, फिर प्रखंडों पर)
  • केवल ब्लॉकों के वास्तव में दृश्यमान चेहरे को चित्रित करना
  • चंक प्रति सूची का उपयोग करना जिसमें दृश्य ब्लॉक होते हैं। दिखाई देने वाले चंक्स इस सूची में खुद को जोड़ लेंगे। यदि वे अदृश्य हो जाते हैं, तो वे स्वचालित रूप से इस सूची से हटा दिए जाते हैं। ब्लॉक पड़ोसी ब्लॉक के निर्माण या नष्ट होने से दिखाई देते हैं।
  • प्रति खंडों की सूचियों का उपयोग करना जिसमें अद्यतन ब्लॉक होते हैं। दृश्यमान ब्लॉक सूची के रूप में समान तंत्र।
  • newगेम लूप के अंदर लगभग कोई स्टेटमेंट का उपयोग न करें । (मेरा खेल लगभग 20 सेकंड तक चलता है जब तक कि कूड़ा उठाने वाले को आमंत्रित नहीं किया जाता)
  • मैं इस समय OpenGL कॉल सूची का उपयोग कर रहा हूं। ( glNewList(), glEndList(), glCallList()) ब्लॉक का एक प्रकार के प्रत्येक पक्ष के लिए।

वर्तमान में मैं प्रकाश व्यवस्था के किसी भी प्रकार का उपयोग नहीं कर रहा हूँ। मैंने वीबीओ के बारे में पहले से ही सुना है। लेकिन मुझे नहीं पता कि यह वास्तव में क्या है। हालाँकि, मैं उनके बारे में कुछ शोध करूँगा। क्या वे प्रदर्शन में सुधार करेंगे? वीबीओ को लागू करने से पहले, मैं glCallLists()कॉल सूची की एक सूची का उपयोग करने और पारित करने का प्रयास करना चाहता हूं । इसके बजाय हजार बार का उपयोग कर glCallList()। (मैं यह कोशिश करना चाहता हूं, क्योंकि मुझे लगता है कि असली MineCraft VBO's का उपयोग नहीं करता है। सही है?)

क्या प्रदर्शन में सुधार करने के लिए अन्य चालें हैं?

VisualVM प्रोफाइलिंग ने मुझे यह दिखाया (केवल 33 फ्रेम के लिए प्रोफाइलिंग, 70 मीटर की दूरी देखने के साथ):

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

40 मीटर (246 फ्रेम) के साथ प्रोफाइलिंग:

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

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

संपादित करें: कुछ synchronisedब्लॉकों और कुछ अन्य छोटे सुधारों को हटाने के बाद । प्रदर्शन पहले से काफी बेहतर है। यहाँ 70 मीटर के साथ मेरे नए रूपरेखा परिणाम हैं:

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

मुझे लगता है कि यह बहुत स्पष्ट है कि selectVisibleBlocksयहाँ मुद्दा है।

अग्रिम में धन्यवाद!
Martijn

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

मुझे लगता है कि मैं जल्द से जल्द वीबीओ लागू करने जा रहा हूं।

PS: सभी स्रोत कोड GitHub: https://github.com/mcourteaux/CraftMania पर उपलब्ध है


2
क्या आप हमें 40 मी पर एक प्रोफाइल शॉट दे सकते हैं ताकि हम देख सकें कि दूसरे की तुलना में तेजी से क्या हो सकता है?
जेम्स

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

@Gtoknu: आप शीर्षक के रूप में क्या सुझाव देते हैं?
मार्टिग्न कोर्टको

5
आप जो पूछते हैं, उसके आधार पर, कुछ लोग कहेंगे कि Minecraft वास्तव में उतना तेज़ नहीं है, या तो।
20

मुझे लगता है कि "कौन सी तकनीक 3 डी गेम को गति दे सकती है" कुछ बेहतर होना चाहिए। कुछ के बारे में सोचो, लेकिन "सर्वश्रेष्ठ" शब्द का उपयोग न करने या किसी अन्य खेल की तुलना करने का प्रयास करें। हम ठीक से नहीं बता सकते हैं कि वे कुछ खेलों में क्या उपयोग करते हैं।
गुस्तावो मैकिएल

जवाबों:


15

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

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

इसके अलावा, आप विश्व-ऊंचाई वाले विखंडू का उपयोग करते हुए दिखाई देते हैं। ध्यान दें कि Minecraft लोड और बचाने के लिए इसके प्रदर्शन सूचियों के लिए क्यूबिकल 16 × 16 × 16 विखंडू का उपयोग करता है । यदि आप ऐसा करते हैं, तो अलग-अलग विखंडू को कम करने का और भी कम कारण है।

(ध्यान दें: मैंने Minecraft के कोड की जांच नहीं की है। इस जानकारी के सभी या तो सुने हुए हैं या मैं अपने खुद के निष्कर्षों को Minecraft के प्रतिपादन से देख रहा हूं जैसा कि मैं खेलता हूं।)


अधिक सामान्य सलाह:

याद रखें कि आपका प्रतिपादन दो प्रोसेसरों पर कार्यान्वित होता है: सीपीयू और जीपीयू। जब आपकी फ्रेम दर अपर्याप्त होती है, तो एक या दूसरा सीमित संसाधन है - आपका प्रोग्राम या तो सीपीयू-बाउंड या जीपीयू-बाउंड है (यह मानकर कि यह स्वैप नहीं है या शेड्यूलिंग समस्याएं नहीं हैं)।

यदि आपका प्रोग्राम 100% CPU पर चल रहा है (और पूरा करने के लिए कोई अन्य कार्य नहीं है), तो आपका CPU बहुत अधिक काम कर रहा है। GPU को अधिक करने के बदले में आपको इसके कार्य को कम करने की कोशिश करनी चाहिए (जैसे कम पुलिंग)। मुझे दृढ़ता से संदेह है कि यह आपकी समस्या है, आपका विवरण दिया गया है।

दूसरी ओर, यदि GPU सीमा है (दुख की बात है, आमतौर पर सुविधाजनक 0% -100% लोड मॉनिटर नहीं हैं) तो आपको यह सोचना चाहिए कि इसे कम डेटा कैसे भेजा जाए, या इसे कम पिक्सेल भरने की आवश्यकता है।


2
महान संदर्भ, आपकी विकि पर आपके शोध का उल्लेख मेरे लिए बहुत उपयोगी था! +1
गुस्तावो मैकिएल

@OP: केवल दृश्यमान चेहरे प्रस्तुत करते हैं ( ब्लॉक नहीं )। एक पैथोलॉजिकल लेकिन मोनोटोनिक 16x16x16 चंक में लगभग 800 दृश्यमान चेहरे होंगे, जबकि निहित ब्लॉकों में 24,000 दृश्यमान चेहरे होंगे। एक बार जब आप ऐसा कर लेते हैं, तो केविन के जवाब में अगले सबसे महत्वपूर्ण सुधार होते हैं।
एंड्रयूज

@KevinReid प्रदर्शन डिबगिंग के साथ मदद करने के लिए कुछ कार्यक्रम हैं। उदाहरण के लिए AMD GPU PerfStudio आपको बताता है कि इसका CPU या GPU बाध्य है और GPU पर कौन सा घटक बाध्य है (बनावट बनाम टुकड़ा बनाम शीर्ष, आदि) और मुझे यकीन है कि Nvidia में भी कुछ ऐसा ही है।
एकलार

3

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

आदर्श रूप से आपकी दुनिया को ऐसे खंडित किया जाएगा कि आप सामान को एक साथ प्रस्तुत करने के लिए समूह बना सकते हैं, वर्टेक्स बफर ऑब्जेक्ट्स का निर्माण कर सकते हैं और उन्हें कई फ्रेमों के साथ फिर से उपयोग कर सकते हैं। आपको केवल एक VBO को संशोधित करने की आवश्यकता होगी यदि दुनिया इसे किसी भी तरह से परिवर्तनों का प्रतिनिधित्व करती है (जैसे उपयोगकर्ता इसे संपादित करता है)। तब आप वीबीओ का निर्माण कर सकते हैं / नष्ट कर सकते हैं, जिसका आप प्रतिनिधित्व कर रहे हैं क्योंकि यह मेमोरी खपत को कम रखने के लिए दृश्यमान होने की सीमा में आता है, आप केवल हिट लेंगे क्योंकि वीबीओ हर फ्रेम के बजाय बनाया गया था।

यदि आपकी प्रोफ़ाइल में "मंगलाचरण" की गिनती सही है, तो आप बहुत सी चीजों को एक भयानक समय कह रहे हैं। (Vec3f.set को 10 मिलियन कॉल ... ouch!)


मैं इस विधि का उपयोग टन के लिए करता हूं। यह बस वेक्टर के लिए तीन मान निर्धारित करता है। यह हर बार एक नई वस्तु को आवंटित करने से बेहतर है।
मार्टिज़न कोर्टो

2

मेरा विवरण (मेरे अपने प्रयोग से) यहां लागू है:

Voxel रेंडरिंग के लिए, क्या अधिक कुशल है: पूर्व-निर्मित VBO या एक ज्यामिति shader?

Minecraft और आपके कोड की निश्चित फ़ंक्शन पाइपलाइन का उपयोग करता है; मेरा प्रयास जीएलएसएल के साथ रहा है, लेकिन आम तौर पर यह लागू होता है, मुझे लगता है:

(मेमोरी से) मैंने एक फ्रुम बनाया जो स्क्रीन फ्रुम से आधा-ब्लॉक बड़ा था। मैंने तब प्रत्येक चंक के केंद्र-बिंदुओं का परीक्षण किया ( मिनीक्राफ्ट में 16 * 16 * 128 ब्लॉक हैं )।

प्रत्येक में चेहरे एक तत्व-सरणी वीबीओ में फैले हुए हैं (विखंडू से कई चेहरे एक ही वीबीओ को तब तक साझा करते हैं जब तक कि यह 'पूर्ण' न हो; ऐसा ही सोचें; mallocउसी वीबीओ में समान बनावट वाले जहां संभव हो) और उत्तर के लिए शीर्ष सूचकांक। चेहरे, दक्षिण चेहरे और इतने पर मिश्रित के बजाय आसन्न हैं। जब मैं आकर्षित करता हूं, तो मैं glDrawRangeElementsउत्तर के चेहरों के लिए करता हूं , सामान्य के साथ पहले से ही अनुमानित और सामान्यीकृत, एक समान रूप में। फिर मैं दक्षिण चेहरे और इतने पर करता हूं, इसलिए मानदंड किसी वीबीओ में नहीं हैं। प्रत्येक चंक के लिए, मुझे केवल उन चेहरों का उत्सर्जन करना होगा जो दिखाई देंगे - केवल स्क्रीन के केंद्र में उन लोगों को बाईं और दाईं ओर खींचने की आवश्यकता है, उदाहरण के लिए; यह GL_CULL_FACEएक आवेदन स्तर पर सरल है।

सबसे बड़ा स्पीडअप, iirc, जब प्रत्येक चंक को पॉलीगॉनिज़िंग करते हुए आंतरिक चेहरे को खींच रहा था।

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

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


मुझे आपके फ्रस्टेशन ऑप्टिमाइज़ेशन का विचार पसंद है। लेकिन क्या आप अपने स्पष्टीकरण में "ब्लॉक" और "चंक" शब्दों को नहीं मिला रहे हैं?
मार्टिज़न कोर्टेको

शायद हाँ। ब्लॉक का एक हिस्सा अंग्रेजी में ब्लॉक का एक ब्लॉक है।
विल

1

आपकी सभी तुलनाएं ( BlockDistanceComparator) कहां से आ रही हैं? यदि यह एक सॉर्ट फ़ंक्शन से है, तो क्या इसे एक रेडिक्स सॉर्ट के साथ बदल दिया जा सकता है (जो कि समान रूप से तेज़ है, और तुलना आधारित नहीं है)?

आपकी टाइमिंग को देखते हुए, भले ही छँटाई खुद उस बुरे से न हो, आपके relativeToOriginफंक्शन को हर compareफंक्शन के लिए दो बार बुलाया जा रहा है; उस डेटा की गणना एक बार की जानी चाहिए। यह एक सहायक संरचना को क्रमबद्ध करने के लिए तेज होना चाहिए

struct DistanceIndexPair
{
    float m_distanceSquaredFromOrigin;
    int m_index;
};

और फिर छद्म कोड में

// for i = 0..numBlocks
//     distanceIndexPairs[i].m_distanceSquaredFromOrigin = ...;
///    distanceIndexPairs[i].m_index = i;
// sort distanceIndexPairs
// for i = 0..numBlocks
//    sortedBlock[i] = unsortedBlocks[ distanceIndexPairs.m_index ]

क्षमा करें यदि यह एक वैध जावा संरचना नहीं है (मैंने अंडरग्रेजुएट के बाद से जावा को नहीं छुआ है) लेकिन उम्मीद है कि आपको यह विचार मिलेगा।


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

1

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

सब कुछ इस तरह से प्रस्तुत करने के बजाय:

प्रस्तुत करना

यह इसे इस तरह प्रस्तुत करता है:

render2

इसका नकारात्मक पक्ष यह है कि आपको शुरुआती विश्व निर्माण पर प्रति चंक की अधिक गणना करनी होगी, या यदि खिलाड़ी किसी ब्लॉक को हटाता / जोड़ता है।

अच्छे प्रदर्शन के लिए बहुत अधिक किसी भी प्रकार के स्वर इंजन की जरूरत होती है।

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

public void greedyMesh(int p, BlockData[][][] blockData){
        boolean[][][][] mask = new boolean[blockData.length][blockData[0].length][blockData[0][0].length][6];

    for(int side=0; side<6; side++){
        for(int x=0; x<blockData.length; x++){
            for(int y=0; y<blockData[0].length; y++){
                for(int z=0; z<blockData[0][0].length; z++){
                    if(data[x][y][z] > Material.AIR && !mask[x][y][z][side] && blockData[x][y][z].faces[side]){
                        if(side == 0 || side == 1){
                            int width = 0;
                            int height = 0;
                            loop:
                            for(int i=y; i<blockData[0].length; i++){
                                if(i == y){
                                    for(int j=z; j<blockData[0][0].length; j++){
                                        if(!mask[x][i][j][side] && blockData[x][i][j].id == blockData[x][y][z].id && blockData[x][i][j].faces[side]){
                                            width++;
                                        }else{
                                            break;
                                        }
                                    }
                                }else{
                                    for(int j=0; j<width; j++){
                                        if(mask[x][i][z+j][side] || blockData[x][i][z+j].id != blockData[x][y][z].id || !blockData[x][i][z+j].faces[side]){
                                            break loop;
                                        }
                                    }
                                }
                                height++;
                            }
                            for(int i=0; i<height; i++){
                                for(int j=0; j<width; j++){
                                    mask[x][y+i][z+j][side] = true;
                                }
                            }

                            if(side == 0)
                                meshes.get(p).add(new Mesh(new VoxelVector3i(x+1, y, z), new VoxelVector3i(x+1, y+height, z+width), new VoxelVector3i(1, 0, 0), Material.getColor(data[x][y][z])));
                            else
                                meshes.get(p).add(new Mesh(new VoxelVector3i(x, y, z+width), new VoxelVector3i(x, y+height, z), new VoxelVector3i(-1, 0, 0), Material.getColor(data[x][y][z])));
                        }else if(side == 2 || side == 3){
                            int width = 0;
                            int height = 0;
                            loop:
                            for(int i=x; i<blockData.length; i++){
                                if(i == x){
                                    for(int j=z; j<blockData[0][0].length; j++){
                                        if(!mask[i][y][j][side] && blockData[i][y][j].id == blockData[x][y][z].id && blockData[i][y][j].faces[side]){
                                            width++;
                                        }else{
                                            break;
                                        }
                                    }
                                }else{
                                    for(int j=0; j<width; j++){
                                        if(mask[i][y][z+j][side] || blockData[i][y][z+j].id != blockData[x][y][z].id || !blockData[i][y][z+j].faces[side]){
                                            break loop;
                                        }
                                    }
                                }
                                height++;
                            }
                            for(int i=0; i<height; i++){
                                for(int j=0; j<width; j++){
                                    mask[x+i][y][z+j][side] = true;
                                }
                            }

                            if(side == 2)
                                meshes.get(p).add(new Mesh(new VoxelVector3i(x, y+1, z+width), new VoxelVector3i(x+height, y+1, z), new VoxelVector3i(0, 1, 0), Material.getColor(data[x][y][z])));
                            else
                                meshes.get(p).add(new Mesh(new VoxelVector3i(x+height, y, z+width), new VoxelVector3i(x, y, z), new VoxelVector3i(0, -1, 0), Material.getColor(data[x][y][z])));
                        }else if(side == 4 || side == 5){
                            int width = 0;
                            int height = 0;
                            loop:
                            for(int i=x; i<blockData.length; i++){
                                if(i == x){
                                    for(int j=y; j<blockData[0].length; j++){
                                        if(!mask[i][j][z][side] && blockData[i][j][z].id == blockData[x][y][z].id && blockData[i][j][z].faces[side]){
                                            width++;
                                        }else{
                                            break;
                                        }
                                    }
                                }else{
                                    for(int j=0; j<width; j++){
                                        if(mask[i][y+j][z][side] || blockData[i][y+j][z].id != blockData[x][y][z].id || !blockData[i][y+j][z].faces[side]){
                                            break loop;
                                        }
                                    }
                                }
                                height++;
                            }
                            for(int i=0; i<height; i++){
                                for(int j=0; j<width; j++){
                                    mask[x+i][y+j][z][side] = true;
                                }
                            }

                            if(side == 4)
                                meshes.get(p).add(new Mesh(new VoxelVector3i(x+height, y, z+1), new VoxelVector3i(x, y+width, z+1), new VoxelVector3i(0, 0, 1), Material.getColor(data[x][y][z])));
                            else
                                meshes.get(p).add(new Mesh(new VoxelVector3i(x, y, z), new VoxelVector3i(x+height, y+width, z), new VoxelVector3i(0, 0, -1), Material.getColor(data[x][y][z])));
                        }
                    }
                }
            }
        }
    }
}

1
और क्या यह इसके लायक है? ऐसा लगता है कि LOD प्रणाली अधिक उपयुक्त होगी।
MichaelHouse

0

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

आप एक अलग जावा वातावरण खोजने की कोशिश कर सकते हैं, या बस आपके पास की सेटिंग्स के साथ गड़बड़ कर सकते हैं, लेकिन अपना कोड बनाने का एक सरल और सरल तरीका, तेज नहीं है, लेकिन एक अच्छा सौदा कम धीमी गति से कम से कम आंतरिक रूप से Vec3f को रोकने के लिए है कोडिंग OOO *। प्रत्येक विधि को स्वयं बनाएं, किसी अन्य कार्य को करने के लिए किसी भी अन्य तरीके को न कहें।

संपादित करें: जबकि वहाँ सभी जगह ओवरहेड है ऐसा प्रतीत होता है कि रेंडर करने से पहले ब्लॉक ऑर्डर करना सबसे खराब प्रदर्शन खाने वाला है। क्या यह सचमुच आवश्यक है? यदि ऐसा है, तो आपको संभवतः एक लूप से गुजरना शुरू करना चाहिए और प्रत्येक ब्लॉक की दूरी की उत्पत्ति के लिए गणना करना चाहिए, और फिर उसी के आधार पर छाँटना चाहिए।

* पीढ़ी वस्तु उन्मुख


हां, आप मेमोरी बचाएंगे, लेकिन सीपीयू खो देंगे! तो OOO भी realtime खेल में बहुत अच्छा नहीं है।
गुस्तावो मैकिएल

जैसे ही आप प्रोफाइलिंग शुरू करते हैं (और सिर्फ नमूना नहीं), जेवीएम सामान्य रूप से गायब हो जाता है। यह क्वांटम सिद्धांत की तरह है, परिणाम का जप किए बिना कुछ नहीं माप सकता: पी
माइकल

@Gtoknu सार्वभौमिक रूप से सत्य नहीं है, OOO के कुछ स्तर पर इनलाइन कोड की तुलना में फंक्शन कॉल अधिक मेमोरी लेने लगते हैं। मैं कहूंगा कि प्रश्न में कोड का एक अच्छा हिस्सा है जो स्मृति के लिए भी ब्रेक के आसपास है।
आआआआआआआआआआआ आआआआआना

0

आप भी बिटकॉइन ऑपरेटरों को गणित के संचालन को तोड़ने की कोशिश कर सकते हैं। यदि आपके पास है 128 / 16, तो एक बिटवाइज़ ऑपरेटर बनाने का प्रयास करें 128 << 4:। यह आपकी समस्याओं में बहुत मदद करेगा। चीजों को पूरी गति से चलाने की कोशिश न करें। अपने गेम को 60 या कुछ की दर से अपडेट करें, और यहां तक ​​कि अन्य चीजों के लिए उसे तोड़ दें, लेकिन आपको वॉक्सल्स को नष्ट करना और या करना होगा या आपको एक टूडू-लिस्ट बनाना होगा, जो आपके एफपीएस को नीचे लाएगा। आप संस्थाओं के लिए लगभग 20 की अपडेट दर कर सकते हैं। और दुनिया अपडेट और या पीढ़ी के लिए 10 जैसी कुछ।

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