एक घटक-आधारित इकाई प्रणाली में स्क्रिप्टेड और "देशी" घटकों को संभालना


11

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

  1. घटकों में केवल स्थिति होती है (उदाहरण के लिए स्थिति, स्वास्थ्य, बारूद गिनती) => तर्क "सिस्टम" में चला जाता है, जो इन घटकों और उनके राज्य को संसाधित करता है (उदाहरण के लिए फ़िज़िक्स सिस्टम, रेंडरसिस्टम, आदि)
  2. मैं शुद्ध C # और स्क्रिप्टिंग (Lua) के माध्यम से घटकों और प्रणालियों को लागू करना चाहता हूं। मूल रूप से मैं पूरी तरह से नए घटकों और प्रणालियों को परिभाषित करने में सक्षम होना चाहता हूं, जो सीधे Lua में मेरे C # स्रोत को पुन: स्थापित किए बिना।

अब मैं विचारों को खोज रहा हूं कि इसे कुशलतापूर्वक कैसे संभालना है, इसलिए मुझे उदाहरण के लिए C # घटकों या Lua घटकों तक पहुंचने के लिए अलग-अलग सिंटैक्स का उपयोग करने की आवश्यकता नहीं है।

मेरा वर्तमान दृष्टिकोण नियमित, सार्वजनिक गुणों का उपयोग करके सी # घटकों को लागू करना होगा, संभवतः कुछ विशेषताओं के साथ संपादक को डिफ़ॉल्ट मान और सामान के बारे में बताया गया है। तब मेरे पास एक C # क्लास "ScriptComponent" होगा, जो एक लुआ टेबल को आंतरिक रूप से लपेटता है और इस तालिका को एक स्क्रिप्ट द्वारा बनाया जाता है और उस विशेष घटक प्रकार के सभी राज्य को पकड़े रहता है। मैं वास्तव में उस स्थिति को C # पक्ष से एक्सेस नहीं करना चाहता हूं, क्योंकि मुझे संकलन समय पर पता नहीं होगा, कि ScriptCompords क्या गुणों के साथ मेरे लिए उपलब्ध होगा। फिर भी, संपादक को उस तक पहुंचने की आवश्यकता होगी, लेकिन निम्नलिखित जैसे एक सरल इंटरफ़ेस को पर्याप्त होना चाहिए:

public ScriptComponent : IComponent
{
    public T GetProperty<T>(string propertyName) {..}
    public void SetProperty<T>(string propertyName, T value) {..}
}

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

हालांकि, लुआ पक्ष से घटकों का उपयोग कैसे करें? अगर मैं कुछ करने के लिए कॉल करता getComponentsFromEntity(ENTITY_ID)हूं जैसे कि मैं शायद केवल मूल सी # घटकों का एक गुच्छा प्राप्त करूंगा, जिसमें "ScriptComponent" भी शामिल है, उपयोगकर्ताडेटा के रूप में। लिपटी हुई लुआ टेबल से मानों को एक्सेस करने से मुझे GetProperty<T>(..)अन्य सी # घटकों के साथ सीधे गुणों तक पहुंचने के बजाय विधि को कॉल करना होगा ।

हो सकता है कि getComponentsFromEntity()केवल एक विशेष विधि लिखी जाए जिसे लुआ से पुकारा जा सके, जो सभी मूल सी # घटकों को उपयोगकर्ताडेटा के रूप में लौटाता है, सिवाय "स्क्रिप्टकंपोनेंट" के, जहां यह बदले हुए टेबल को लौटाएगा। लेकिन अन्य घटक-संबंधित तरीके होंगे और मैं वास्तव में C # कोड या Lua स्क्रिप्ट से कॉल करने के लिए इन सभी विधियों की नकल नहीं करना चाहता।

अंतिम लक्ष्य सभी प्रकार के घटकों को एक ही तरह से संभालना होगा, जिसमें कोई विशेष मामला वाक्यविन्यास नहीं होगा, जो मूल घटकों और लुआ घटकों के बीच विभेदित हो - विशेषकर लुआ पक्ष से। जैसे मैं एक Lua स्क्रिप्ट लिखने में सक्षम होना चाहता हूँ:

entity = getEntity(1);
nativeComponent = getComponent(entity, "SomeNativeComponent")
scriptComponent = getComponent(entity, "SomeScriptComponent")

nativeComponent.NativeProperty = 5
scriptComponent.ScriptedProperty = 3

स्क्रिप्ट को इस बात की परवाह नहीं करनी चाहिए कि यह वास्तव में किस तरह का घटक है और मैं उन्हीं तरीकों का उपयोग करना चाहूंगा जिन्हें मैं घटकों को पुनः प्राप्त करने, जोड़ने या हटाने के लिए C # की ओर से उपयोग करूंगा।

हो सकता है कि इस तरह इकाई प्रणालियों के साथ स्क्रिप्टिंग को एकीकृत करने के कुछ नमूना कार्यान्वयन हैं?


1
क्या आप लुआ का उपयोग करने पर अटक गए हैं? मैंने इसी तरह की बातें सी # एप्लिकेशन की स्क्रिप्टिंग के साथ की है, अन्य सीएलआर भाषाओं को रनटाइम (मेरे मामले में बू) में पार्स किया जा रहा है। क्योंकि आप पहले से ही एक प्रबंधित वातावरण में उच्च-स्तरीय कोड चला रहे हैं और यह सभी IL के अंतर्गत है, इसलिए "स्क्रिप्टिंग" पक्ष से मौजूदा कक्षाओं को उप-वर्ग करना आसान है और उन वर्गों के उदाहरणों को होस्ट एप्लिकेशन पर वापस भेजना है। मेरे मामले में, मैं भी लोडिंग की गति के लिए स्क्रिप्ट की संकलित असेंबली को कैश कर दूंगा, और स्क्रिप्ट बदलने पर बस इसे फिर से बनाऊंगा।
जस्टिन

नहीं, मैं लुआ का उपयोग नहीं कर रहा हूं। व्यक्तिगत रूप से मैं इसकी सादगी, छोटे आकार, गति और लोकप्रियता के कारण इसका उपयोग करना पसंद करूंगा (इसलिए लोगों की संभावना पहले से ही अधिक होने लगती है), लेकिन मैं विकल्पों के लिए खुला हूं।
मारियो

क्या मैं पूछ सकता हूं कि आप C # और आपके स्क्रिप्ट वातावरण के बीच समान परिभाषा क्षमताओं की इच्छा क्यों रखते हैं? सामान्य डिज़ाइन स्क्रिप्टिंग भाषा में C # और फिर 'ऑब्जेक्ट असेंबली' में घटक की परिभाषा है। मैं सोच रहा हूं कि क्या मुद्दा उठा है कि यह समाधान है?
जेम्स

1
लक्ष्य घटक प्रणाली को C # स्रोत कोड के बाहर से एक्स्टेंसिबल बनाना है। एक्सएमएल या स्क्रिप्ट फ़ाइलों में संपत्ति मूल्यों को स्थापित करने के माध्यम से ही नहीं, बल्कि पूरे नए गुणों के साथ नए घटकों को परिभाषित करके और उन्हें संसाधित करने वाले नए सिस्टम। यह काफी हद तक स्कॉट बिलास के डंगऑन सीज में ऑब्जेक्ट सिस्टम के विवरण से प्रेरित है, जहां उनके पास "मूल" सी ++ घटक और साथ ही एक "GoSkritComponent" है, जो खुद एक स्क्रिप्ट के लिए केवल एक आवरण है: scbbilas.com/games/dungeon -सीज
मारियो

एक स्क्रिप्टिंग या प्लगइन इंटरफ़ेस के निर्माण के जाल में गिरने से इतना जटिल है कि यह मूल उपकरण (इस मामले में C # या विजुअल स्टूडियो) को फिर से लिखता है।
डी जुवे

जवाबों:


6

FxIII के उत्तर का एक सहसंबंध यह है कि आपको स्क्रिप्टिंग भाषा में पहले (या कम से कम एक बहुत ही सभ्य भाग) सब कुछ डिजाइन करना चाहिए ताकि यह सुनिश्चित किया जा सके कि आपका एकीकरण तर्क वास्तव में मॉडिंग के लिए प्रावधान करता है। जब आप निश्चित हों कि आपका स्क्रिप्टिंग एकीकरण बहुमुखी है तो C # में आवश्यक बिट्स को फिर से लिखें।

मैं व्यक्तिगत रूप से C # 4.0 में dynamicसुविधा से नफरत करता हूं (मैं एक स्थिर भाषा नशेड़ी हूं) - लेकिन यह संदेह के बिना एक परिदृश्य है जहां इसका उपयोग किया जाना चाहिए और जहां यह वास्तव में चमकता है। आपके C # घटक बस मजबूत / विस्तृत व्यवहार वाली वस्तुएं होंगी ।

public class Villian : ExpandoComponent
{
    public void Sound() { Console.WriteLine("Cackle!"); }
}

//...

dynamic villian = new Villian();
villian.Position = new Vector2(10, 10); // Add a property.
villian.Sound(); // Use a method that was defined in a strong context.

आपके लुआ घटक पूरी तरह से गतिशील होंगे (ऊपर दिए गए एक ही लेख से आपको यह अंदाजा लगाना चाहिए कि इसे कैसे लागू किया जाए)। उदाहरण के लिए:

// LuaSharp is my weapon of choice.
public class LuaObject : DynamicObject
{
    private LuaTable _table;

    public LuaObject(LuaTable table)
    {
        _table = table;
    }

    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        var methodName = binder.Name;
        var function = (LuaFunction)_table[methodName];
        if (function == null)
        {
            return base.TryInvokeMember(binder, args, out result);
        }
        else
        {
            var resultArray = function.Call(args);
            if (resultArray == null)
                result = null;
            else if (resultArray.Length == 1)
                result = resultArray[0];
            else
                result = resultArray;
            return true;
        }
    }

    // Other methods for properties etc.
}

अब क्योंकि आप उपयोग कर रहे हैं dynamicआप Lua वस्तुओं का उपयोग कर सकते हैं जैसे कि वे C # में वास्तविक वर्ग थे।

dynamic cSharpVillian = new Villian();
dynamic luaVillian = new LuaObject(_script["teh", "villian"]);
cSharpVillian.Sound();
luaVillian.Sound(); // This will call into the Lua function.

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

2

मैं इसके विपरीत करना चाहता हूं: एक डायनेमिक भाषा का उपयोग करते हुए सभी लिखें और फिर टोंटी (यदि कोई हो) को ट्रैक करें। एक बार जब आप पाते हैं कि आप C # या (बल्कि) C / C ++ का उपयोग करके शामिल कार्यात्मकताओं को चुनिंदा रूप से लागू कर सकते हैं।

मैं आपको यह मुख्य रूप से बताता हूं क्योंकि जो करने की कोशिश कर रहे हैं वह आपके सिस्टम की फ्लेक्सिबिलिटी को सी # भाग में सीमित करना है; जैसा कि सिस्टम जटिल हो जाता है आपका सी # "इंजन" एक गतिशील दुभाषिया की तरह दिखने लगेगा, शायद सबसे अच्छा नहीं। सवाल यह है कि क्या आप अपना अधिकांश समय जेनेरिक C # इंजन लिखने में या अपने खेल को बढ़ाने के लिए निवेश करने के लिए तैयार हैं?

यदि आपका लक्ष्य दूसरा है, जैसा कि मैं मानता हूं, तो आप शायद अपने समय का उपयोग गेम मैकेनिक्स पर ध्यान केंद्रित करने में करेंगे, जो कि एक अनुभवी दुभाषिया को गतिशील कोड चलाने की अनुमति देगा।


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

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

4
+1 हालांकि मैं इसके लिए एक और कारण से सहमत हूं - यदि आप चाहते हैं कि आपका गेम एक्स्टेंसिबल हो, तो आपको अपने कुत्ते का खाना खाना चाहिए: आप केवल अपने संभावित मोडिंग समुदाय को खोजने के लिए एक स्क्रिप्ट इंजन को एकीकृत करने के लिए उतर सकते हैं, जो वास्तव में कुछ भी नहीं बना सकते हैं यह।
जोनाथन डिकिंसन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.