शीर्षक जानबूझकर अतिशयोक्तिपूर्ण है और यह सिर्फ पैटर्न के साथ मेरी अनुभवहीनता हो सकती है लेकिन यहाँ मेरा तर्क है:
संस्थाओं को लागू करने का "सामान्य" या यकीनन सीधा तरीका उन्हें वस्तुओं के रूप में लागू करना और सामान्य व्यवहार को उपवर्गित करना है। की क्लासिक समस्या के लिए यह होता है "एक है EvilTreeकी एक उपवर्ग Treeया Enemy?"। यदि हम कई विरासत की अनुमति देते हैं, तो हीरे की समस्या पैदा होती है। हम इसके बजाय संयुक्त कार्यप्रणाली को आगे बढ़ा सकते हैं Treeऔर Enemyआगे चलकर पदानुक्रम को बढ़ा सकते हैं जो ईश्वर वर्गों की ओर जाता है, या हम जानबूझकर अपने Treeऔर Entityकक्षाओं में व्यवहार को छोड़ सकते हैं (उन्हें चरम मामले में इंटरफेस बना EvilTreeसकते हैं ) ताकि खुद को लागू किया जा सके - जो आगे बढ़ता है कोड दोहराव अगर हम कभी भी एक SomewhatEvilTree।
इकाई-घटक प्रणाली को विभाजित करके इस समस्या को हल करने का प्रयास करें Treeऔर Enemyविभिन्न घटकों में वस्तु - कहते हैं Position, Healthऔर AI- और लागू इस तरह के एक के रूप में प्रणाली, AISystemकि ऐ निर्णय के अनुसार एक Entitiy की स्थिति बदल जाती है। अब तक तो अच्छा है लेकिन क्या हो EvilTreeसकता है अगर कोई पॉवरअप उठा सकता है और नुकसान का सामना कर सकता है? पहले हमें एक की जरूरत है CollisionSystemऔर DamageSystem(हम शायद पहले से ही ये हैं)। इसके CollisionSystemसाथ संवाद करने की आवश्यकताएं DamageSystem: हर बार दो चीजें CollisionSystemएक संदेश को भेजती हैं DamageSystemताकि यह स्वास्थ्य को घटा सके। नुकसान पॉवरअप से भी प्रभावित होता है इसलिए हमें इसे कहीं स्टोर करने की आवश्यकता है। क्या हम एक नया बनाते हैं PowerupComponentजिसे हम संस्थाओं से जोड़ते हैं? लेकिन फिर दDamageSystemइसके बारे में कुछ जानने की जरूरत है, इसके बारे में कुछ नहीं जानना चाहिए - आखिरकार, ऐसी चीजें भी हैं जो नुकसान का सौदा करती हैं जो पावरअप (जैसे Spike) नहीं उठा सकती हैं । क्या हम इस उत्तर के समान क्षति गणना के लिए भी इसे PowerupSystemसंशोधित करने की अनुमति देते हैं ? लेकिन अब दो सिस्टम एक ही डेटा को एक्सेस करते हैं। जैसा कि हमारा खेल अधिक जटिल हो जाता है, यह एक अमूर्त निर्भरता ग्राफ बन जाएगा, जहां कई प्रणालियों के बीच घटक साझा किए जाते हैं। उस बिंदु पर हम सिर्फ वैश्विक स्थिर चर का उपयोग कर सकते हैं और सभी बॉयलरप्लेट से छुटकारा पा सकते हैं।StatComponent
क्या इसे हल करने का कोई प्रभावी तरीका है? एक विचार मुझे घटकों को कुछ कार्य करने देना था, उदाहरण के लिए, StatComponent attack()जो डिफ़ॉल्ट रूप से पूर्णांक देता है, लेकिन जब एक पावरअप हो सकता है:
attack = getAttack compose powerupBy(20) compose powerdownBy(40)
यह उस समस्या को हल नहीं करता attackहै जिसे कई प्रणालियों द्वारा एक्सेस किए गए घटक में सहेजा जाना चाहिए, लेकिन कम से कम मैं फ़ंक्शन ठीक से टाइप कर सकता हूं अगर मेरे पास एक भाषा है जो इसे पर्याप्त रूप से समर्थन करती है:
// In StatComponent
type Strength = PrePowerup | PostPowerup
type Damage = Int
type PrePowerup = Int
type PostPowerup = Int
attack: Strength = getAttack //default value, can be changed by systems
getAttack: PrePowerup
// these functions can be defined in other components or in PowerupSystems
powerupBy: Strength -> PostPowerup
powerdownBy: Strength -> PostPowerup
subtractArmor: Strength -> Damage
// in DamageSystem
dealDamage: Damage -> () = attack compose subtractArmor compose hurtSomeEntity
इस तरह मैं कम से कम सिस्टम द्वारा जोड़े गए विभिन्न कार्यों के सही क्रम की गारंटी देता हूं। किसी भी तरह से, ऐसा लगता है कि मैं तेजी से कार्यात्मक प्रतिक्रियाशील प्रोग्रामिंग के लिए यहां आ रहा हूं इसलिए मैं खुद से पूछता हूं कि क्या मुझे शुरू से ही इसका इस्तेमाल नहीं करना चाहिए था (मैंने केवल एफआरपी में देखा है, इसलिए मैं यहां गलत हो सकता हूं)। मैं देखता हूं कि ईसीएस जटिल वर्ग पदानुक्रमों में सुधार है, लेकिन मैं आश्वस्त नहीं हूं कि यह आदर्श है।
क्या इसके आसपास कोई हल है? क्या ECS को अधिक साफ-सुथरा बनाने के लिए एक कार्यक्षमता / पैटर्न मुझे याद आ रहा है? क्या इस समस्या के लिए एफआरपी केवल कड़ाई से बेहतर है? क्या ये समस्याएँ जो मैं कार्यक्रम करने की कोशिश कर रहा हूँ, उसमें निहित जटिलता से उत्पन्न हो रही है; यानी एफआरपी के समान मुद्दे होंगे?