"गेम ऑब्जेक्ट" - और घटक-आधारित डिज़ाइन


25

मैं पिछले 3-4 वर्षों में कुछ शौक परियोजनाओं पर काम कर रहा हूं। बस सरल 2d और 3 डी खेल। लेकिन हाल ही में मैंने एक बड़ा प्रोजेक्ट शुरू किया है। पिछले कुछ महीनों में मैं एक गेम ऑब्जेक्ट क्लास डिज़ाइन करने की कोशिश कर रहा हूं जो मेरे सभी गेम ऑब्जेक्ट्स का आधार हो सकता है। इसलिए बहुत कोशिश और मरने के बाद मैंने Google का रुख किया, जिसने मुझे जल्दी से कुछ जीडीसी पीडीएफ और पॉवर पॉइंट्स की ओर इशारा किया। और अब मैं घटक-आधारित गेम ऑब्जेक्ट्स की समझ प्राप्त करने की कोशिश कर रहा हूं।

मैं समझता हूं कि इंजन एक गेम ऑब्जेक्ट बनाता है और फिर विभिन्न घटकों को संलग्न करता है जो स्वास्थ्य, भौतिकी, नेटवर्किंग जैसी चीजों को संभालते हैं और जो कुछ भी आप उन्हें करते हैं। लेकिन मुझे समझ में नहीं आता है कि वाई कैसे वस्तु की स्थिति बदल गया है तो घटक एक्स जानता है। जैसे कि PhysicsComponent को कैसे पता चलता है कि खिलाड़ी जीवित है, क्योंकि HealthComponent द्वारा स्वास्थ्य को नियंत्रित किया जाता है ..? और HealthComponent "प्लेयर-डेड-एनीमेशन" कैसे निभाता है?

मैं इस धारणा के तहत था कि यह कुछ इस तरह था (HealthComponent में):

if(Health < 0) {
   AnimationComponent.PlayAnimation("played-died-animation")
}

लेकिन फिर, HealthComponent को कैसे पता चलता है कि एनीमेशन ऑब्जेक्ट के साथ गेम ऑब्जेक्ट जुड़ा हुआ है? एकमात्र समाधान जो मैं यहां देख रहा हूं वह है

  1. यह देखने के लिए जाँच करें कि क्या कोई ऐनिमेशनकम्पोनेंट संलग्न है या नहीं (या तो घटक कोड के अंदर या इंजन की तरफ)

  2. घटकों को अन्य घटकों की आवश्यकता होती है, लेकिन ऐसा लगता है कि पूरे घटक-डिजाइन से लड़ते हैं।

  3. जैसे लिखें, HealthWithAnimationComponent, HealthNoAnimationComponent, और soo, जो फिर से पूरे घटक-डिजाइन विचार से लड़ने के लिए लगता है।


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

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

जवाबों:


11

आपके सभी उदाहरणों में, एक भयानक समस्या है। स्वास्थ्य घटक को प्रत्येक घटक प्रकार के बारे में जानने की जरूरत है जो कि इकाई के मरने का जवाब देने की आवश्यकता हो सकती है। इसलिए, आपका कोई भी परिदृश्य उपयुक्त नहीं है। आपकी इकाई में एक स्वास्थ्य घटक है। इसमें एक एनीमेशन घटक है। न तो दूसरे पर निर्भर हैं और न ही उसके बारे में जानते हैं। वे एक संदेश प्रणाली के माध्यम से संवाद करते हैं।

जब स्वास्थ्य घटक यह पता लगाता है कि इकाई 'मर गई' है, तो यह एक 'I die' संदेश भेजता है। उपयुक्त संदेश को चलाकर इस संदेश का जवाब देना एनीमेशन घटक की जिम्मेदारी है।

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


ओके, यह समझ में आता है। लेकिन कौन "राज्यों" को 'मृत', या 'पोर्टल-इस-टूट', आदि घटक या इंजन घोषित करता है? क्योंकि एक राज्य 'मृत' को एक ऐसी चीज से जोड़ना जो कभी भी स्वास्थ्यवर्धक न हो, मेरे लिए थोड़े बेकार लगता है। मुझे लगता है कि मैं बस में गोता लगाऊंगा और कुछ कोड का परीक्षण करूंगा और देखूंगा कि क्या काम करता है।
hayer

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

बस जिज्ञासु, आप एक MovementComponent को कैसे संभालेंगे? जब यह इनपुट का पता लगाता है, तो इसे स्थितिComponent में वेग बढ़ाने की आवश्यकता होती है। संदेश कैसा दिखेगा?
Tips48

8

जिस तरह से आर्टेमिस समस्या को हल करता है वह घटकों के भीतर प्रसंस्करण नहीं करना है। अवयवों में केवल वही डेटा होता है जिसकी उन्हें आवश्यकता होती है। सिस्टम कई घटक प्रकारों को पढ़ते हैं और जो भी आवश्यक हो प्रसंस्करण करते हैं।

तो, आपके मामले में, आपके पास एक RenderSystem हो सकता है जो HealthComponent (और अन्य) में पढ़ता है और उचित एनिमेशन के साथ कतार बजाता है। डेटा को इस तरह से अलग करने से निर्भरता को ठीक से प्रबंधित करने में आसानी होती है।


यह समस्या को संभालने का एक अच्छा तरीका होता है: घटक गुणों का प्रतिनिधित्व करते हैं जबकि सिस्टम एक साथ गुणों को जोड़ते हैं और काम करने के लिए उपयोग करते हैं। यह पारंपरिक OOP सोच से दूर एक बड़ी पारी है और कुछ लोगों के सिर पर चोट करता है =)
पैट्रिक ह्यूजेस

ओके, अब मैं वास्तव में खो गया हूं .. "इसके विपरीत, एक ईएस में, यदि आपके पास एक युद्ध के मैदान में 100 इकाइयां हैं, प्रत्येक को एक इकाई द्वारा दर्शाया गया है, तो आपके पास प्रत्येक विधि की शून्य प्रतियां हैं जो एक इकाई पर मंगाई जा सकती हैं - क्योंकि एंटिटीज़ में विधियाँ नहीं होती हैं। सिस्टम। " एक GunComponent में डेटा कहाँ संग्रहीत किया गया है? जैसे राउंड, आदि। यदि सभी इकाइयां समान घटक साझा करती हैं।
हायर

1
जहां तक ​​मैं समझता हूं कि सभी इकाइयां एक ही घटक को साझा नहीं करती हैं, प्रत्येक इकाई के पास एन घटक उदाहरण हो सकते हैं। एक सिस्टम तब सभी संस्थाओं की एक सूची के लिए खेल पर सवाल उठाता है जिनके पास घटक उदाहरण हैं जो वे उनसे जुड़ी परवाह करते हैं और फिर उन पर जो भी प्रसंस्करण करते हैं
जेक वुड्स

यह बस समस्या को चारों ओर ले जाता है। एक प्रणाली कैसे जानती है कि किन घटकों का उपयोग करना है? एक प्रणाली को अन्य प्रणालियों की भी आवश्यकता हो सकती है (स्टेटमैचिन प्रणाली उदाहरण के लिए एनीमेशन के लिए कॉल कर सकती है)। हालाँकि, यह WHO की समस्या का समाधान डेटा का मालिक है। वास्तव में, एक सरल कार्यान्वयन के लिए खेल वस्तु में एक शब्दकोश होना चाहिए और प्रत्येक प्रणाली वहाँ में अपने चर बनाती है।
ADB

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

6

आपके कोड में आप तरीके हैं (मैंने उन्हें इस्तेमाल किया, संभवतः कुछ अन्य तरीके मौजूद हैं) यह जानने के लिए कि क्या वस्तु बदली हुई स्थिति है:

  1. मेसेज भेजें।
  2. घटक से सीधे डेटा पढ़ें।

1) यह देखने के लिए एक जाँच करें कि क्या कोई ऐनिमेशनकम्पोनेंट संलग्न है या नहीं (या तो घटक कोड के अंदर या इंजन की तरफ)

इसके लिए मैंने उपयोग किया, 1. गेमकॉजेक्ट का हसकॉन्पटेंट फंक्शन, या 2. जब आप कंपोनेंट को अटैच करते हैं तो आप कुछ कंस्ट्रक्शन फंक्शन में निर्भरता की जांच कर सकते हैं, या 3. अगर मुझे पता है कि ऑब्जेक्ट में यह कंपोनेंट है, तो मैं इसका इस्तेमाल करता हूं।

2) घटकों को अन्य घटकों की आवश्यकता होती है, लेकिन यह पूरे घटक-डिजाइन से लड़ने के लिए लगता है।

कुछ लेखों में मैंने पढ़ा है, कि आदर्श प्रणाली में घटक एक दूसरे पर निर्भर नहीं करते हैं, लेकिन वास्तविक जीवन में ऐसा नहीं है।

3) लिखें, HealthWithAnimationComponent, HealthNoAnimationComponent, और soo, जो फिर से पूरे घटक-डिजाइन विचार से लड़ने के लिए लगता है।

ऐसे घटकों को लिखना एक बुरा विचार है। अपने ऐप में मैंने स्वास्थ्य घटक को सबसे स्वतंत्र बनाया है। अब मैं कुछ ऑब्जर्वर पैटर्न के बारे में सोच रहा हूं जो कुछ विशिष्ट घटना (जैसे "हिट", "हील" आदि) के बारे में ग्राहकों को सूचित करता है। तो एनीमेशनकम्पोनेंट को एनीमेशन कब खेलना है, यह खुद तय करना होगा।

लेकिन जब मैंने सीबीईएस के बारे में लेख पढ़ा है तो इसने मुझे प्रभावित किया, इसलिए मैं अब बहुत खुश हूं जब मैं सीबीईएस का उपयोग करता हूं और इसकी नई संभावनाओं की खोज करता हूं।


1
खैर, google.no/… @ स्लाइड १६
हिरन

@bobenko, कृपया CBES के बारे में लेख का लिंक दें। मैं इसमें बहुत दिलचस्प हूं;)
एडवर्ड 83

1
और lambdor.net/?p=171 @ बॉटम, मेरे प्रश्न के सारांश का यह प्रकार है कि सापेक्ष कार्यक्षमता, गैर-प्राथमिक घटकों के संदर्भ में विभिन्न कार्यक्षमता को कैसे परिभाषित किया जा सकता है? सबसे प्राथमिक घटक क्या हैं? किस तरह से प्राथमिक घटक शुद्ध कार्यों से अलग हैं? मौजूदा घटक स्वचालित रूप से नए घटकों से नए संदेशों के साथ कैसे संवाद कर सकते हैं? उस संदेश को अनदेखा करने का क्या मतलब है जो एक घटक को नहीं पता है? आखिर इनपुट-प्रोसेस-आउटपुट मॉडल का क्या हुआ?
हेयर

1
यहाँ CBES stackoverflow.com/ / 3495647/903195 पर अच्छा जवाब है जिन लेखों पर मैंने शोध किया है उनमें से अधिकांश इस उत्तर से हैं। मैंने काउबॉयप्रोग्रामिंग.com/2007/01/05/evolve - your - heirachy से शुरुआत की और फिर रत्न 5 में (जैसा कि मुझे याद है) उदाहरणों के साथ अच्छा लेख था।
येवैन

लेकिन एक और अवधारणा कार्यात्मक-प्रतिक्रियाशील प्रोग्रामिंग के बारे में क्या है, मेरे लिए यह सवाल अभी भी खुला है, लेकिन आपके लिए हो सकता है कि शोध के लिए एक अच्छी दिशा है।
येवैन

3

माइकल, पैट्रिक ह्यूजेस और ब्लेकी जैसे इसके कहते हैं। बस समस्या को इधर-उधर करने से बचने का उपाय यह है कि विचारधारा को छोड़ दिया जाए जो समस्या का कारण बनता है।

इसके कम OOD और अधिक कार्यात्मक प्रोग्रामिंग की तरह। जब मैंने घटक-आधारित डिज़ाइन के साथ प्रयोग करना शुरू किया, तो मैंने इस मुद्दे को सड़क पर देखा। मैंने कुछ और गुगली की, और मैंने समाधान के रूप में "कार्यात्मक प्रतिक्रियाशील प्रोग्रामिंग" पाया।

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

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

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