घटक-आधारित गेम में एंटिटी स्टेट्स और एनिमेशन को कैसे अपडेट करें?


10

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

मैं घटक के बीच निर्भरता को रोकने के लिए घटक के अंदर एक अद्यतन () विधि नहीं करना चाहता।

वर्तमान में मेरे मन में यह है कि घटक डेटा को पकड़ते हैं और सिस्टम घटकों को अपडेट करते हैं।

इसलिए, अगर मेरे पास कुछ संस्थाओं (जैसे खिलाड़ी, दुश्मन 1, दुश्मन 2) के साथ एक सरल 2 डी गेम है जिसमें ट्रांसफ़ॉर्म, मूवमेंट, स्टेट, एनीमेशन और रेंडरिंग घटक हैं, तो मुझे लगता है कि मुझे होना चाहिए:

  • एक मूवमेंट सिस्टम जो सभी मूवमेंट घटकों को स्थानांतरित करता है और स्टेट घटकों को अपडेट करता है
  • और एक रेंडरसिस्टम जो एनिमेशन घटकों को अपडेट करता है (एनीमेशन घटक में प्रत्येक राज्य के लिए एक एनीमेशन (यानी फ्रेम / बनावट का एक सेट) होना चाहिए और इसे अपडेट करने का मतलब है कि वर्तमान राज्य के अनुरूप एनीमेशन का चयन करना (जैसे कूदना, मूविंग_लेफ्ट, आदि), और फ्रेम इंडेक्स अपडेट करना)। फिर, रेंडरसिस्टम प्रत्येक इकाई के एनीमेशन के वर्तमान फ्रेम के अनुरूप बनावट के साथ रेंडर घटकों को अपडेट करता है और स्क्रीन पर सब कुछ प्रस्तुत करता है।

मैंने आर्टेमिस फ्रेमवर्क जैसे कुछ कार्यान्वयन देखे हैं, लेकिन मुझे नहीं पता कि इस स्थिति को कैसे हल किया जाए:

मान लीजिए कि मेरे खेल में निम्नलिखित संस्थाएँ हैं। प्रत्येक इकाई में राज्यों का एक सेट और प्रत्येक राज्य के लिए एक एनीमेशन होता है:

  • खिलाड़ी: "बेकार", "चलती_ ठीक", "कूद"
  • दुश्मन 1: "मूविंग_अप", "मूविंग_डाउन"
  • शत्रु २: "मूविंग_लेफ्ट", "मूविंग_ राइट"

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

जैसा कि आप देख सकते हैं, मैं यहाँ बहुत खो गया हूँ, इसलिए मैं किसी भी मदद की बहुत सराहना करूँगा।

संपादित करें: मुझे लगता है कि इस काम को करने का हल मैं जैसा चाहता हूं, यह है:

आप सभी संस्थाओं के लिए उपयोग किए जाने के लिए पर्याप्त रूप से स्टेटकंपोनेंट और एनीमेशनकॉम्पोनेंट जेनेरिक बनाते हैं। उनके पास जो डेटा है, वह चीजों को बदलने के लिए संशोधक होगा जैसे कि एनिमेशन खेला जाता है या कौन से राज्य उपलब्ध हैं। - बाइट 56

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


मुझे लगता है कि आपने इसे देखा है: संस्थाओं या घटकों में राज्य परिवर्तन ? क्या आपका प्रश्न मौलिक रूप से उस एक से अलग है?
MichaelHouse

@ Byte56 हां, मैंने पढ़ा है कि कुछ घंटे पहले। आपके द्वारा सुझाया गया समाधान उस विचार के समान है जो मैंने यहां उजागर किया है। लेकिन मेरी समस्या तब आती है जब स्टेटकंपोनेंट और एनिमेशन.कॉमपॉइंटेंट सभी संस्थाओं के लिए समान नहीं होते हैं जो सिस्टम को प्रभावित करते हैं। क्या मुझे उस सिस्टम को उन छोटे सिस्टम में विभाजित करना चाहिए जो उन संस्थाओं के समूहों को प्रोसेस करते हैं जिनके पास समान राज्य और एनिमेशन हैं? (बेहतर स्पष्टीकरण के लिए मेरी मूल पोस्ट का अंतिम भाग देखें)
miviclin

1
आप सभी संस्थाओं के लिए उपयोग किए जाने के लिए पर्याप्त statecomponentऔर animationcomponentसामान्य बनाते हैं । उनके पास जो डेटा है, वह चीजों को बदलने के लिए संशोधक होगा जैसे कि एनिमेशन खेला जाता है या कौन से राज्य उपलब्ध हैं।
MichaelHouse

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

@ADB मैं डेटा निर्भरता के बारे में बात कर रहा हूँ। एनीमेशन को अपडेट करने के लिए (उदाहरण के लिए Move_right एनीमेशन से Move_left एनीमेशन में परिवर्तन) मुझे इकाई की वर्तमान स्थिति जानने की आवश्यकता है और मैं नहीं देखता कि इन 2 घटकों को अधिक सामान्य कैसे बनाया जाए।
मिविकलिन

जवाबों:


5

IMHO Movementघटक को वर्तमान स्थिति ( Movement.state) को पकड़ना चाहिए और Animationघटक को परिवर्तनों का अवलोकन करना चाहिए Movement.stateऔर उसके Animation.animationअनुसार अपने वर्तमान एनीमेशन ( ) को अपडेट करना चाहिए, ताकि राज्य आईडी के एक साधारण लुकअप को एनीमेशन के रूप में उपयोग किया जा सके (जैसा कि ओपी के अंत में सुझाव दिया गया है)। जाहिर है कि यह साधन Animationनिर्भर करेगा Movement

एक वैकल्पिक संरचना में एक सामान्य Stateघटक होगा, जो Animationअवलोकन Movementकरता है, और संशोधित करता है, जो मूल रूप से मॉडल-व्यू-नियंत्रक (इस मामले में राज्य-एनीमेशन-आंदोलन) है।

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

सौभाग्य।


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

पहला मामला: नियंत्रणMovement होगा (निरीक्षण नहीं)। अंतिम मामला: हाँ ऐसा होगा या, और इस तरह के आयोजन को सुनने वाले अन्य सभी घटक इसे प्राप्त करेंगे। प्रदर्शन शुद्ध विधि कॉल की तुलना में अधिक बुरा है, लेकिन ज्यादा नहीं। आप उदाहरण के लिए इवेंट ऑब्जेक्ट्स को पूल कर सकते हैं। Btw, आपको "इवेंट नोड" के रूप में इकाई का उपयोग करने की आवश्यकता नहीं है, आप अपनी इकाई वर्ग को पूरी तरह से छोड़कर एक समर्पित "इवेंट बस" का उपयोग कर सकते हैं। StateMovemententity.dispatchEvent(...);
टॉरिट

2

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

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

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

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

विभिन्न गेम ऑब्जेक्ट्स के लिए आप विभिन्न राज्यों / एनीमेशन से पूछें जाने वाली समस्या के बारे में, यहां मैं क्या करूंगा । सबसे पहले, मुझे कार्यान्वयन के इस स्तर पर बहुत अधिक फैंसी नहीं मिलेगा: केवल इसे लागू करने के लिए जो आपको चाहिए, उसे लागू करें, फिर घंटियाँ और सीटी जोड़ें जैसा कि आपको उनकी आवश्यकता है।

इसलिए, मैं 'स्टेट' घटक के साथ शुरुआत करूंगा: PlayerStateComponent, Enemy1State, Enemy2State। राज्य घटक उचित समय पर राज्य को बदलने का ध्यान रखेगा। राज्य आपके सभी वस्तुओं में बहुत सुंदर है, इसलिए यह GameObject में निवास कर सकता है।

फिर, एक एनिमेशनकॉममेन्ट होगा। इसमें राज्य के लिए एनिमेशन का एक शब्दकोश होगा। अपडेट () में, यदि राज्य बदलता है तो एनीमेशन बदल दें।

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

मेरे द्वारा प्रस्तावित कार्यान्वयन काफी भोली है, लेकिन यहां कुछ संभावित सुधार हैं क्योंकि आप अधिक उपयोग-मामला जोड़ते हैं:

  • एक शब्दकोश के साथ GameObject चर को बदलें। प्रत्येक घटक मूल्यों को संग्रहीत करने के लिए शब्दकोश का उपयोग करता है। (टक्कर को ठीक से संभालना सुनिश्चित करें ...)
  • सादे संदर्भों के शब्दकोश को संदर्भों के साथ बदलें: वर्ग फ़्लोटवरिबल () {सार्वजनिक मूल्य [...]}
  • कई राज्य घटक के बजाय, एक सामान्य स्थिति बनाएँ जिसमें आप वैरिएबल स्टेट मशीन बना सकते हैं। आपको एक सामान्य स्थिति सेट करने की आवश्यकता होती है, जिस पर एक राज्य बदल सकता है: कुंजी प्रेस, माउस इनपुट, चर परिवर्तन (आप इसे फ़्लोटविरेबल ऊपर टाई कर सकते हैं)।

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

0

एडीबी के जवाब के अलावा आप http://en.wikipedia.org/wiki/D dependency_injection का उपयोग कर सकते हैं , जो तब मदद करता है जब आपको उनके घटकों के संदर्भ के रूप में उन्हें पारित करने के माध्यम से बहुत सारे घटकों का निर्माण करने की आवश्यकता होती है। जाहिर है कि वे अब भी एक-दूसरे पर निर्भर रहेंगे (यदि आपके कोड बेस में यह आवश्यक है), लेकिन आप उस निर्भरता को एक ही स्थान पर रख सकते हैं, जहां निर्भरता सेटअप है और आपके कोड के बाकी को निर्भरता के बारे में जानने की आवश्यकता नहीं है।

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

सरल सिस्टम के लिए आप DI या क्लीन कोड का उपयोग किए बिना दूर हो सकते हैं, आपकी RenderingSystem कक्षाएं लगता है कि आपको उन्हें सांख्यिकीय रूप से कॉल करने की आवश्यकता है या कम से कम उन्हें प्रत्येक घटक में उपलब्ध है, जो उन्हें बहुत अधिक एक दूसरे पर निर्भर करता है और बदलने के लिए कठिन बनाता है। यदि आप अधिक स्वच्छ दृष्टिकोण में रुचि रखते हैं तो ऊपर दिए गए DI विकी लिंक के लिंक की जाँच करें और क्लीन कोड के बारे में पढ़ें: http://clean-code-developer.com/


मेरे पास पहले से ही एक प्रणाली है जहां घटक एक दूसरे पर काफी निर्भर हैं। मैंने वहां निर्भरता इंजेक्शन का भारी उपयोग किया, और हालांकि मैं इसे गहरी पदानुक्रम पर पसंद करता हूं, मैं घटक युग्मन से बचने के लिए एक नया बनाने की कोशिश कर रहा हूं यदि यह संभव था। मैं कुछ भी वैधानिक रूप से नहीं कहूंगा। मेरे पास एक ComponentManager होगा जिसे हर सिस्टम एक्सेस करता है (हर सिस्टम में इसका एक संदर्भ होना चाहिए), और RendererSystem को कंपोनेंट मैनेजर से सभी एनीमेशन कंपोनेंट मिलेंगे और प्रत्येक एनिमेशन की वर्तमान स्थिति को रेंडर करेंगे।
मैविक्लिन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.