नमस्ते। मैं एक अनुभवी एकता डेवलपर हूँ। मैंने Hackernoon और Tatum Games की प्रतियोगिता में भाग लेने का निर्णय लिया। पहले लेख में, मैं एकता खेल विकास परियोजनाओं की वास्तुकला पर चर्चा करूँगा और उन सबसे सामान्य दृष्टिकोणों पर चर्चा करूँगा जिनका मैंने सामना किया है। और, निश्चित रूप से, मैं आपको बताऊंगा कि मैं इतना मसोचिस्ट क्यों हूं और मैं अपने प्रिय HMVС (HMVP) के पास क्यों आया। पुनश्च यहाँ वर्णित सभी एक व्यक्तिपरक राय है। सभी को विकास और परियोजना की बारीकियों पर समग्र रूप से विचार करने की आवश्यकता है, लेकिन सामान्य तौर पर, सबसे अच्छा आर्किटेक्चर वह है जो मौजूद नहीं है और टीम के लिए सुविधाजनक और कुशल शैली में विभिन्न दृष्टिकोणों को जोड़ती है: डी मोनो व्यवहार और घटक-उन्मुख प्रोग्रामिंग (COP) आइए सबसे बुनियादी दृष्टिकोण से शुरू करें जो ज्यादातर शुरुआती लोगों द्वारा उपयोग किया जाता है। मैं यह नहीं कहना चाहता कि यह दृष्टिकोण खराब है, बस अधिकांश डेवलपर्स ओओपी (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग) के संदर्भ में सोचने के आदी हैं। सीओपी (घटक-उन्मुख प्रोग्रामिंग) के सही उपयोग के लिए कुछ अलग मानसिकता की आवश्यकता होती है। उसी समय, यूनिटी का मोनोबिहेवियर-आधारित सीओपी का कार्यान्वयन आदर्श नहीं दिखता है। तो, मूल दृष्टिकोण का तात्पर्य है कि पूरा गेम एक GameObject पर MonoBehaviour घटकों के साथ बनाया जाएगा, जो आपको विभिन्न उप-प्रणालियों को छोटे टुकड़ों में तोड़ने और उस से गेम बनाने की अनुमति देता है। { private Awake() { } } हालाँकि, शैतान विवरण में है। यह दृष्टिकोण स्केलिंग कठिनाइयों का कारण बनता है, विशेष रूप से बड़ी परियोजनाओं पर, अनावश्यक लिंकिंग, एकता के हुड के तहत समस्याओं को दूर करना, और यूनिटी एपीआई के लिए एक मजबूत टाई, जो बाद में समस्याएँ पैदा कर सकता है, खासकर यदि आप क्लाइंट पर कोड डुप्लिकेट करना चाहते हैं और सर्वर। एकाकी वस्तु प्रबंधन के लिए सिंगलटन पहली और सबसे भयानक चीज है जो दिमाग में आ सकती है। इसके सार में, सिंगलटन दृश्य या संपूर्ण परियोजना में निहित एक वस्तु है, जिसे हमारे खेल में अलग-अलग प्रणालियों को बांधने और प्रबंधित करने के लिए आवश्यक है। सिंगलटन का एक सरल उदाहरण, जिसे मैं अक्सर जूनियर डेवलपर्स में देखता हूं: public sealed class MySingleton { private static MySingleton _instance = null; private MySingleton() { } public static MySingleton Instance { get { if (_instance == null) { _instance = new MySingleton(); } return _instance; } } public void OperationX() { } } छोटी परियोजनाओं पर, इससे अनावश्यक समस्याएँ नहीं होंगी। परियोजना जितनी बड़ी होगी, नियंत्रण करना उतना ही बुरा होगा। मेमोरी लीक का उल्लेख नहीं करने के लिए, सिंगलटन बिल्डिंग टेस्ट, मल्टीथ्रेडिंग के आयोजन और बहुत लंबी स्क्रिप्ट (अक्सर नौसिखिए डेवलपर्स में देखा जाता है) के मुद्दों की ओर ले जाता है। सिंगलटन संगठन आमतौर पर कैसा दिखता है (और सबसे सही होने से बहुत दूर है) के बारे में यहां थोड़ा सा है: तो, आपको कैसे पता चलेगा कि सिंगलटन दुष्ट है? जब यह आपके खेल में सभी तर्कों को बांधता है और सब कुछ नियंत्रित करता है जब लिंक का एक गुच्छा सीधे इसमें डाला जाता है जब इसका आकार बहुत बड़ा हो जाता है जब आप डिबगिंग या मेमोरी प्रबंधन में पहले ही अपना पैर जमा चुके होते हैं, खासकर अगर सिंगलटन एक गेमऑब्जेक्ट है सिंगलटन का उपयोग करना बेहतर कब होता है? छोटी परियोजनाएँ जब स्मृति प्रबंधन कोई समस्या नहीं है, और आप सीधे लिंक अग्रेषित करने के बजाय ईवेंट प्रबंधित करते हैं छोटे सिस्टम के लिए, उदाहरण के लिए, ऑडियो का प्रबंधन करने के लिए या एनालिटिक्स सिस्टम के लिए समापन बिंदु अधिग्रहण के रूप में अब डीआई कंटेनरों पर चर्चा करते हैं। डि कंटेनर और कमबख्त ज़ेनजेक्ट ओह-ओह, बहुत से लोग जेनजेक्ट के लिए जोर दे रहे हैं और डीआई कंटेनर का उपयोग करके निर्भरता को लागू कर रहे हैं। वास्तव में, बहुत से लोग इस विशाल ढांचे का उपयोग नियमित सिंगलटन के रूप में करते हैं। हमेशा की तरह, मैंने इसे परियोजनाओं पर देखा है: इसके सार में, अंतिम वस्तुओं में संदर्भ डालने और निर्भरताओं को हल करने के लिए एक डी कंटेनर की आवश्यकता होती है। उसी ज़ेनजेक्ट से सबसे सरल उदाहरण: public class TestInstaller : MonoInstaller { public override void InstallBindings() { Container.Bind<string>().FromInstance("Hello World!"); Container.Bind<Greeter>().AsSingle().NonLazy(); } } public class Greeter { public Greeter(string message) { Debug.Log(message); } } यह दृष्टिकोण अच्छा है, लेकिन केवल तब तक जब तक चीजें जटिल न होने लगें: DI-कंटेनर अनिवार्य रूप से सिंगलटन के समान है, लेकिन इसमें सुधार हुआ है, जो कंटेनर को ही बांधता है बहुत बार, "किलोमीटर-लॉन्ग" इंस्टॉलर क्लास बनाए जाते हैं जो डिपेंडेंसी बाइंडिंग करते हैं नवागंतुकों के लिए जिम्मेदारी के अधिक पृथक्करण की कीमत पर समझना मुश्किल है, हालांकि बाद में एक अच्छी तरह से मापनीय दृष्टिकोण कंटेनरों और सर्वव्यापी बाइंडिंग के कारण डिबग करना मुश्किल है एक साधारण DI कंटेनर को सर्विस लोकेटर में बदलना बहुत आसान है बेशक, डीआई कंटेनर सही हाथों में कोड व्यवस्थित करने का एक अच्छा तरीका है, लेकिन चीजों को बैचेनलिया में उतरने से रोकने के लिए आपको उच्च स्तर के प्रशिक्षण की आवश्यकता है। एमवीसी अपने शुद्ध रूप में अपने शुद्ध रूप में क्यों? क्योंकि इसे समझना काफी आसान है। हमारे पास एक परियोजना को व्यवस्थित करने के लिए एक नियंत्रक, मॉडल और दृश्य है। लेकिन जब तक एमवीसी है, एमवीपी, एमवीवीएम, आदि के रूप में इसके कई उपप्रकार हैं। लेकिन अभी के लिए हम बुनियादी और सभी के लिए सुलभ उदाहरणों पर ध्यान केंद्रित करेंगे: लाभ स्पष्ट हैं - हम नियंत्रण (उपयोगकर्ता इनपुट) को डेटा से और दृश्य से अलग करते हैं (उपयोगकर्ता स्क्रीन पर क्या देखता है)। संचार आमतौर पर ईवेंट-संचालित होता है और एप्लिकेशन कंटेनर में प्रारंभ किया जाता है। यह अधिक सामंजस्य की आवश्यकता को दूर करता है; हम केवल घटनाओं के साथ संवाद करते हैं। हालाँकि, यहाँ कुछ कमियाँ हैं: प्रोजेक्ट स्केल के रूप में, हमारा इंस्टॉलेशन क्लास एप्लिकेशन (एक ही कंटेनर) बढ़ता है एमवीसी की क्षैतिज व्यवस्था एक दूसरे से जुड़े विभिन्न वर्गों की एक बड़ी संख्या बनाती है अब दूसरे तरीके पर चर्चा करते हैं। कंटेनरों में एमवीसी एक और संभावित परिदृश्य हमारे एमवीसी ट्रायड को डी कंटेनर में जोड़ना है। इस तरह, हम एप्लिकेशन के बीच कनेक्शन को बेहतर ढंग से नियंत्रित कर सकते हैं, लेकिन हर चीज को सर्विस लोकेटर में बदलना बहुत आसान है। दृष्टिकोण अलग है क्योंकि नियंत्रकों को घटनाओं से जोड़ने के बजाय, हम अपने नियंत्रकों को एक कंटेनर के माध्यम से हल करते हैं और फिर घटनाओं के साथ काम करते हैं। हालाँकि, सामान्य DI-कंटेनर की तरह यहाँ भी समस्याएँ उत्पन्न होती हैं, लेकिन घटना की जटिलता बढ़ जाती है और अधिक वर्ग निर्मित हो जाते हैं। हालाँकि, हम प्रतिनिधित्व, मॉडल और नियंत्रकों को अलग करते हैं। एचएमवीसी / एचएमवीपी यह वह जगह है जहां मैं थोड़ी लंबी बात करना चाहता हूं, क्योंकि मैं, एक स्वपीड़ितवादी के रूप में, इस दृष्टिकोण का काफी शौकीन हो गया हूं। इसके साथ, हम अपने एमवीसी का एक पेड़ जैसा विभाजन बनाते हैं, जो बहुत अधिक बढ़ते कोड आधार के बावजूद कई फायदे देता है। इसलिए, आइए सबसे अधिक बार उपयोग की जाने वाली इंटरेक्शन स्कीम को देखें: यह कैसे काम करता है? प्रारंभ में, हम GameInstaller के साथ एक खाली दृश्य बनाते हैं, जो प्रत्येक दृश्य के लिए कंटेनरों को अलग से लोड करेगा। GameInstaller वर्ग स्वयं वैश्विक (शीर्ष-स्तर) ट्रायड्स को संग्रहीत करता है जो आमतौर पर बड़े सिस्टम (उदाहरण के लिए, ऑडियो हैंडलिंग) के लिए ज़िम्मेदार होते हैं और पूरे गेम के जीवनचक्र के लिए सामान्य घटनाओं को संग्रहीत करते हैं। फिर GameInstaller आपके लिए आवश्यक दृश्य कंटेनर को लोड करता है, जो अपने अंदर शीर्ष-स्तरीय ट्रायड्स को इनिशियलाइज़ करता है (उदाहरण के लिए, एक सामान्य प्लेयर कंट्रोलर), और बदले में, चाइल्ड कंट्रोलर्स को अपने अंदर इनिशियलाइज़ करेगा (उदाहरण के लिए, एक तोप नियंत्रक)। और ऐसे ही उतरता चला जाता है। सभी शाखाओं का संचार विशेष रूप से घटनाओं और गतिशील क्षेत्रों के माध्यम से होता है। यह जटिल लगता है, लेकिन यह बहुत आसान है: यह दृष्टिकोण हमें अपने बच्चों के बीच पर्याप्त प्रासंगिक संबंध बनाए रखते हुए आसानी से सभी त्रिभुजों को अलग करने की अनुमति देता है। प्रत्येक प्रस्तुतकर्ता को प्रारंभ करना माता-पिता से घटनाओं का संदर्भ प्राप्त करने के साथ शुरू होता है। मुझे इस दृष्टिकोण में कई फायदे दिखाई देते हैं: प्रोजेक्ट के दृश्यों को लगभग तुरंत लोड किया जा सकता है, और हमारे ऑब्जेक्ट, जिसमें व्यू भी शामिल है, को डिमांड पर इनिशियलाइज़ किया जा सकता है क्योंकि हमारा ट्री लोड होता है। यदि हमें कोई ईवेंट भेजने से पहले सेटिंग्स या गेम स्टोर के साथ व्यू लोड करने की आवश्यकता नहीं है, तो हम ईवेंट के अलावा कुछ भी स्टोर नहीं करते हैं अलग-अलग तीनों की कड़ी संरचना और अलगाव घटनाओं के कारण कमजोर सामंजस्य घटनाओं की कीमत पर गतिशील कंटेनरों के बजाय ट्रायड शाखाओं पर डिबग करना काफी आसान है कुछ कमियां हैं: यदि आपको किसी घटना को 20 त्रय के पेड़ के माध्यम से पिरोने की आवश्यकता है, तो यह काफी लंबा उपक्रम होगा, लेकिन दृष्टिकोण में अच्छी प्रारंभिक डिजाइन शामिल है परियोजना के लिए बड़ा कोडबेस, हालांकि अच्छी तरह से संरचित यदि आपको शाखाओं को आपस में जोड़ने की आवश्यकता है, तो आपके लिए एक दर्जन वर्गों के माध्यम से घटनाओं को फेंकना एक बड़ी चुनौती हो सकती है सामान्य तौर पर, एचएमवीसी / एचएमवीपी को उप-प्रणालियों के उच्च अलगाव, उच्च स्मृति आवश्यकताओं और खेल संसाधनों के साथ सुव्यवस्थित परियोजनाओं के लिए आवश्यक है। लेकिन अन्य तरीकों की तुलना में इसकी आदत पड़ने में अधिक समय लग सकता है। निष्कर्ष किसी परियोजना को आयोजित करने के प्रत्येक दृष्टिकोण का अपना स्थान है। यह सब सिर्फ डिजाइन लक्ष्य पर निर्भर करता है। यदि आपको तंग वास्तुकला और तेज़ मेमोरी हैंडलिंग की आवश्यकता है और तेज़ और गतिशील संसाधनों की आवश्यकता है - एचएमवीसी लें। यदि आपको अपने प्रोजेक्ट को जल्दी से बिना उपद्रव के प्रोटोटाइप बनाने की आवश्यकता है - सिंगलटन में सब कुछ लिखें।