एंटिटीज और कंपोनेंट्स में तरीकों को स्टोर करना एक बुरा विचार क्यों है? (कुछ अन्य एंटिटी सिस्टम प्रश्नों के साथ।)


16

यह इस सवाल का एक अनुवर्ती है , जिसका मैंने उत्तर दिया, लेकिन यह एक बहुत विशिष्ट विषय से निपटता है।

इस जवाब ने मुझे Entity Systems को लेख से बेहतर समझने में मदद की।

मैंने Entity Systems के बारे में लेख (हाँ) पढ़ा है , और इसने मुझे निम्नलिखित बताया:

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

यह कई स्थितियों में वास्तव में व्यावहारिक लगता है, लेकिन घटकों के बारे में सिर्फ डेटा कक्षाएं होने का हिस्सा मुझे परेशान कर रहा है। उदाहरण के लिए, मैं एक इकाई प्रणाली में अपने वेक्टर 2 डी वर्ग (स्थिति) को कैसे लागू कर सकता हूं?

वेक्टर 2 डी वर्ग डेटा रखता है: एक्स और वाई निर्देशांक, लेकिन इसकी विधियां भी हैं, जो इसकी उपयोगिता के लिए महत्वपूर्ण हैं और कक्षा को केवल दो तत्व सरणी से अलग करते हैं। उदाहरण तरीके हैं: add(), rotate(point, r, angle), substract(), normalize(), और अन्य सभी मानक, उपयोगी और बिल्कुल जरूरत तरीकों पदों (जो Vector2D वर्ग के उदाहरण हैं) होना चाहिए कि।

यदि घटक सिर्फ एक डेटा धारक था, तो यह इन विधियों के लिए सक्षम नहीं होगा!

एक समाधान जो संभवतः पॉप हो सकता है, उन्हें सिस्टम के अंदर लागू करना होगा, लेकिन यह बहुत ही सहज ज्ञान युक्त लगता है। ये विधियां ऐसी चीजें हैं जो मैं अब प्रदर्शन करना चाहता हूं , उन्हें पूरा करने और उपयोग करने के लिए तैयार हैं। मैं MovementSystemसंदेशों के कुछ महंगे सेट को पढ़ने के लिए इंतजार नहीं करना चाहता जो इसे एक इकाई की स्थिति पर गणना करने के लिए निर्देश देते हैं!

और, लेख बहुत स्पष्ट रूप से बताता है कि केवल सिस्टम में कोई कार्यक्षमता होनी चाहिए , और उसके लिए एकमात्र स्पष्टीकरण, जो मुझे मिल सकता है, "ओओपी से बचने के लिए" था। सबसे पहले, मुझे समझ में नहीं आता है कि मुझे संस्थाओं और घटकों में तरीकों का उपयोग करने से क्यों बचना चाहिए। मेमोरी ओवरहेड व्यावहारिक रूप से समान है, और जब सिस्टम के साथ युग्मित किया जाता है, तो उन्हें दिलचस्प तरीकों से लागू करना और संयोजित करना बहुत आसान होना चाहिए। उदाहरण के लिए, सिस्टम केवल संस्थाओं / घटकों को बुनियादी तर्क प्रदान कर सकता है, जो स्वयं कार्यान्वयन को जानते हैं। यदि आप मुझसे पूछते हैं - यह मूल रूप से ES और OOP दोनों से माल ले रहा है, तो कुछ ऐसा जो लेख के लेखक के अनुसार नहीं किया जा सकता है, लेकिन मुझे एक अच्छा अभ्यास लगता है।

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

और सिर्फ एक अन्य बात ... क्या भंडारण घटकों की बात आती है तो वास्तव में सरणियों का एक विकल्प है? मैं किसी इकाई वर्ग के अंदर सरणियों के अलावा संग्रहीत किए जाने वाले घटकों के लिए कोई अन्य स्थान नहीं देखता ...

हो सकता है, यह एक बेहतर तरीका है: घटकों को संस्थाओं के सरल गुणों के रूप में संग्रहीत करें। उदाहरण के लिए, एक स्थिति घटक को चिपकाया जाएगा entity.position

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


अलेक्जेंडर आप सिर्फ एक और बिल्ला पाने के लिए बहुत सारे संपादन कर रहे हैं? क्योंकि वह नटखट शरारती है, यह प्राचीन धागों का एक टन टकराता रहता है।
झॉकिंग

जवाबों:


25

मुझे लगता है कि घटकों में डेटा तक पहुंचने, अद्यतन करने या हेरफेर करने के लिए सरल तरीके होना पूरी तरह से ठीक है। मुझे लगता है कि घटकों से बाहर रहना चाहिए कि कार्यक्षमता तार्किक कार्यक्षमता है। उपयोगिता कार्य ठीक हैं। याद रखें, इकाई-घटक प्रणाली सिर्फ एक दिशानिर्देश है, न कि सख्त नियमों का पालन करना चाहिए। उनका पालन करने के लिए अपने रास्ते से बाहर मत जाओ। अगर आपको लगता है कि यह एक तरह से करने के लिए अधिक समझ में आता है, तो इसे इस तरह से करें :)

संपादित करें

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

हालाँकि, कुछ विरासत होना ठीक है! आप एक ऐसी भाषा के साथ काम कर रहे हैं जो विरासत से बहुत प्रभावित है, इसका कोई उपयोग नहीं करना बहुत मुश्किल है। उदाहरण के लिए, आपके पास एक Componentवर्ग या इंटरफ़ेस हो सकता है जो आपके अन्य सभी घटकों का विस्तार या कार्यान्वयन करता है। अपनी Systemकक्षा के साथ समान व्यवहार करें । इससे चीजें बहुत आसान हो जाती हैं। मैं दृढ़ता से अनुशंसा करता हूं कि आप आर्टेमिस ढांचे पर एक नज़र डालें । यह खुला स्रोत है और इसकी कुछ उदाहरण परियोजनाएं हैं। उन चीजों को खोलें और देखें कि यह कैसे काम करता है।

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

संस्थाओं और घटकों को एक अलग प्रबंधक में संग्रहीत किया जाता है।

आपके द्वारा उल्लिखित रणनीति, अपने स्वयं के घटकों ( entity.position) को स्टोर करने के लिए, इकाई घटक थीम के विरुद्ध है, लेकिन अगर आपको लगता है कि यह सबसे अधिक समझ में आता है, तो यह पूरी तरह से स्वीकार्य है।


1
हम्म, यह स्थिति को बहुत सरल करता है, धन्यवाद! मैंने सोचा था कि कुछ जादू "आप बाद में पछता रहे हैं" बात चल रही है, और मैं इसे देख नहीं पाया!
जकोरा

1
ना, मैं पूरी तरह से अपनी इकाई घटक प्रणाली में उनका उपयोग करता हूं। यहां तक ​​कि मेरे पास कुछ घटक हैं जो एक आम माता-पिता से प्राप्त होते हैं, हांफते हैं । मुझे लगता है कि केवल पछतावा आपको करना होगा अगर आपने इस तरह के तरीकों का उपयोग करने के लिए काम करने की कोशिश की । यह सब करने के बारे में है जो आपको सबसे अधिक समझ में आता है। यदि यह विरासत का उपयोग करने या किसी घटक में कुछ तरीके डालने के लिए समझ में आता है, तो इसके लिए जाएं।
MichaelHouse

2
मैंने इस विषय पर अपने अंतिम उत्तर से सीख लिया है। अस्वीकरण: मैं यह नहीं कह रहा हूँ यह है जिस तरह से यह करने के लिए। :)
MichaelHouse

1
हाँ, मुझे पता है कि एक नए प्रतिमान को सीखना कितना कठिन हो सकता है। सौभाग्य से, आप चीजों को आसान बनाने के लिए पुराने प्रतिमान के पहलुओं का उपयोग करते हैं! मैंने भंडारण जानकारी के साथ अपना उत्तर अपडेट कर दिया है। यदि आप आर्टेमिस को देखते हैं, तो जांच लें EntityManagerकि चीजें कहां संग्रहीत हैं।
MichaelHouse

1
अच्छा! जब यह किया जाता है कि एक बहुत प्यारा इंजन होने जा रहा है। इसके साथ गुड लक! दिलचस्प सवाल पूछने के लिए धन्यवाद।
MichaelHouse

10

'वह' लेख वह नहीं है जिससे मैं विशेष रूप से सहमत हूं, इसलिए मेरा उत्तर कुछ महत्वपूर्ण होगा जो मुझे लगता है।

यह कई स्थितियों में वास्तव में व्यावहारिक लगता है, लेकिन घटकों के बारे में सिर्फ डेटा कक्षाएं होने का हिस्सा मुझे परेशान कर रहा है। उदाहरण के लिए, मैं एक इकाई प्रणाली में अपने वेक्टर 2 डी वर्ग (स्थिति) को कैसे लागू कर सकता हूं?

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

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

और, लेख बहुत स्पष्ट रूप से बताता है कि केवल सिस्टम में कोई कार्यक्षमता होनी चाहिए, और उसके लिए एकमात्र स्पष्टीकरण, जो मुझे मिल सकता है, "ओओपी से बचने के लिए" था। सबसे पहले, मुझे समझ में नहीं आता है कि मुझे संस्थाओं और घटकों में तरीकों का उपयोग करने से क्यों बचना चाहिए।

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

इस तरह से इसके बारे में सोचो; एक खेल में कई अलग-अलग प्रकार की आकर्षित करने योग्य वस्तुएं होती हैं। पुराने चित्र, एनिमेशन (अपडेट (), getCurrentFrame (), आदि), इन आदिम प्रकारों के संयोजन, और वे सभी बस एक ड्रॉ प्रदान कर सकते हैं () पद्धति रेंडर करने के लिए [...]

एक घटक आधारित प्रणाली का विचार यह है कि आपके पास इन के लिए अलग-अलग कक्षाएं नहीं होंगी, लेकिन एक एकल ऑब्जेक्ट / इकाई वर्ग होगा, और छवि एक ऑब्जेक्ट / इकाई होगी जिसमें एक ImageRenderer होगा, एनिमेशन एक वस्तु / होगा इकाई जिसमें एक एनिमेशनरेंडर है, आदि। संबंधित सिस्टम को पता होगा कि इन घटकों को कैसे रेंडर करना है और इसलिए ड्रॉ () विधि के साथ किसी भी आधार वर्ग की आवश्यकता नहीं होगी।

[...] जिसके बाद किसी इकाई के स्प्राइट को कैसे लागू किया जाता है, इसके बारे में केवल इंटरफ़ेस (ड्रा) और स्थिति के बारे में परवाह करने की आवश्यकता नहीं है। और फिर, मुझे केवल एक एनीमेशन सिस्टम की आवश्यकता होगी जो एनीमेशन-विशिष्ट तरीकों को कॉल करेगा जिसका प्रतिपादन से कोई लेना-देना नहीं है।

ज़रूर, लेकिन यह घटकों के साथ अच्छी तरह से काम नहीं करता है। आपके पास 3 विकल्प हैं:

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

और सिर्फ एक अन्य बात ... क्या भंडारण घटकों की बात आती है तो वास्तव में सरणियों का एक विकल्प है? मैं किसी इकाई वर्ग के अंदर सरणियों के अलावा संग्रहीत किए जाने वाले घटकों के लिए कोई अन्य स्थान नहीं देखता ...

आप सिस्टम में घटकों को स्टोर कर सकते हैं। सरणी समस्या नहीं है, लेकिन जहाँ आप घटक को संग्रहीत करते हैं।


+1 दूसरे दृष्टिकोण के लिए धन्यवाद। इस तरह के अस्पष्ट विषय से निपटने के दौरान कुछ प्राप्त करना अच्छा है! यदि आप सिस्टम में घटकों को स्टोर कर रहे हैं, तो क्या इसका मतलब यह है कि घटकों को केवल एक सिस्टम द्वारा संशोधित किया जा सकता है? उदाहरण के लिए, ड्राइंग सिस्टम और मूवमेंट सिस्टम दोनों ही स्थिति घटक तक पहुंच प्राप्त करेंगे। आप इसे कहाँ स्टोर करते हैं?
MichaelHouse

खैर वे केवल उन घटकों के लिए एक पॉइंटर को स्टोर करेंगे, जो तब तक कर सकते हैं, जब तक मैं चिंतित हूं कि कहीं न कहीं ... इसके अलावा, आप सिस्टम में घटकों को क्यों स्टोर करेंगे? क्या इसका कोई फायदा है?
जकोरा

क्या मैं सही हूँ, @ कायलोटन? मैं इसे कैसे करूंगा, यह तर्कसंगत लगता है ...
jcora

एडम / टी-मशीन के उदाहरण में, इरादा यह है कि प्रति घटक 1 प्रणाली है, लेकिन एक प्रणाली निश्चित रूप से अन्य घटकों को एक्सेस और संशोधित कर सकती है। (यह घटकों के
बहुपरत

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

2

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


मुझे पता है कि, लेकिन समस्या यह है कि कॉलिंग के तरीके तेज़ हैं और सिस्टम द्वारा मौके पर किया जा सकता है, या कुछ और जो किसी इकाई की स्थिति में हेरफेर करने की आवश्यकता हो सकती है। मैंने समझाया कि, इसकी जांच करो, यह भी, प्रश्न इसके अलावा भी बहुत कुछ है, मुझे विश्वास है।
जकोरा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.