2010-08-09 33 views
10

मुझे यह विधि मिली (एकता सी # स्क्रिप्ट के अंदर), लेकिन मुझे समझ में नहीं आता कि "उपज" भाग वास्तव में कैसे काम करता है।यह "उपज" कार्य के साथ विस्तार से कैसे काम करता है?

मुझे एमएसडीएन से पता है कि फ़ंक्शन एक आईन्यूमेरेटर लौटाएगा जिसे मैं फिर से चला सकता हूं, लेकिन यह कोड 1,5 सेकंड तक प्रतीक्षा करता है और फिर से नहीं मिलता है क्योंकि इसका मतलब यह होगा कि अंदर बनाई गई वस्तुओं को कई बार बनाया गया था। कोई भी जो मुझे समझा सकता है कि यह कोड कैसे काम करता है?

IEnumerator DestroyShip() 
{ 
    // create new gameobject 
    Instantiate(ExplosionPrefab, transform.position, transform.rotation); 
    // make current gameobject invisible 
    gameObject.renderer.enabled = false; 
    // set new position for the current gameobject 
    transform.position = new Vector3(0f, transform.position.y, transform.position.z); 
    // wait for 1,5 seconds 
    yield return new WaitForSeconds(1.5f); 
    // make the current gameobject visible again 
    gameObject.renderer.enabled = true; 
} 
+0

प्रश्न शीर्षक अधिक वर्णनात्मक हो सकता है। हालांकि, Google ने अभी भी कीवर्ड उठाए हैं। – ftvs

उत्तर

21

गणनाकार संकलक आपके लिए बनाए गए दोहराया जा रहा है हो सकता है। एक बार।

कंपाइलर एक कक्षा उत्पन्न करेगा जो आईन्यूमेरेटर लागू करता है, जिसमें MoveNext() फ़ंक्शन और वर्तमान प्रॉपर्टी है। कक्षा में सभी सदस्यों को कॉल के बीच समारोह की स्थिति को स्टोर करने की आवश्यकता होगी। सटीक विवरण "कंपाइलर जादू" माना जा सकता है।

इस जेनरेटेड क्लास का ऑब्जेक्ट, यूनिटी 3 डी इंजन द्वारा संभाला और प्रबंधित किया जाएगा। यूनिटी 3 डी इंजन हर फ्रेम में एक बार प्रत्येक सक्रिय कोरआउट पर MoveNext() को कॉल करेगा (जब तक कि अन्यथा निर्देश न दिया जाए)।

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

अपने प्रश्न का उत्तर देने के लिए: आपके फ़ंक्शन में कोड एक बार निष्पादित किया जाएगा, लेकिन यह 'उपज वापसी' कथन पर रोक देगा।

ऊपर बताए अनुसार, एक विशेष ऑब्जेक्ट जो आईएन्यूमेरेटर लागू करता है सी # कंपाइलर द्वारा बनाया गया है।

MoveNext करने के लिए पहली कॉल पर(), अपने कार्य एक विस्फोट बनाता है और "नया WaitForSeconds (1.5f)" के लिए वर्तमान वस्तु तय करता है।

यूनिटी 3 डी इंजन इस ऑब्जेक्ट का निरीक्षण करता है, यह देखता है कि यह विशेष वर्ग "वेटफॉरसेकंड्स" का एक उदाहरण है, इसलिए कुछ प्रतीक्षा कतार पर गणक को रखता है, और 1.5 सेकंड पास होने तक दूसरे तत्व के लिए नहीं पूछेगा। इस बीच, कई फ्रेम प्रस्तुत किए जाएंगे और विस्फोट खेला जाएगा।

1.5 सेकंड के बाद, एकता कतार से प्रगणक grap, और MoveNext() फिर से फोन होगा। आपके फ़ंक्शन का दूसरा भाग अब निष्पादित होगा, लेकिन दूसरी ऑब्जेक्ट उत्पन्न करने में विफल रहेगा। MoveNext() यह एक नए तत्व है, जो unity3d के संकेत दूर इस प्रगणक फेंकने के लिए है प्राप्त करने में विफल इंगित करने के लिए अवास्तविक लौटाते हैं। कचरा कलेक्टर समय में कुछ बिंदु पर स्मृति को पुनः प्राप्त होगा।

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

+0

उस कोड को एक स्टैंडअलोन सी # प्रोजेक्ट में लिखना, और आईएलएसपीई में उत्पन्न जेनेट असेंबली को देखते हुए यह एक त्वरित आंख खोलने वाला है कि सभी जादू कैसे काम करते हैं। –

5

तो yield एक बार प्रयोग किया जाता है, यह है कि तुम क्यों धारणा है कि यह पुनरावृति नहीं करता है, के रूप में यदि आप एक तत्व के साथ एक IEnumerator लौट रहे थे।

यह उपज कीवर्ड का एक अजीब उपयोग है, यह समझना मुश्किल है कि इसे पूरे संदर्भ को देखे बिना क्यों लागू किया गया था।

+1

इसे "स्टार्टकोराउटिन" नामक फ़ंक्शन में कॉल किया जाता है: यूनिटी.स्टार्टकोराउटिन (डिस्ट्रॉयशिप), मुझे लगता है कि यह यूनिटी इंजन के लिए बहुत विशिष्ट है http://unity3d.com –

+0

संदर्भ: http://unity3d.com/support/documentation /ScriptReference/MonoBehaviour.StartCoroutine.html –

+1

मैं देखता हूं ... अच्छा, यह निश्चित रूप से यूनिटी इंजन के संदर्भ में समझ में आता है। –

1

IEnumerator के बजाय IEnumerable वापस करना बेहतर है क्योंकि यह अधिक स्पष्ट और उपयोग करने में आसान है। IEnumerable<T> का उपयोग करना बेहतर है। यील्ड रिटर्न एक इटरेटर ब्लॉक को लागू करने के लिए सिंटैक्टिक चीनी है, संकलक रिलीज कोड उत्पन्न करता है क्योंकि यह अनिवार्य रूप से मानक बॉयलर प्लेट है जिसे आसानी से प्रोग्रामेटिक रूप से जेनरेट किया जा सकता है। जब आप एक कार्रवाई की एक श्रृंखला बनाने के लिए चाहते हैं तो आप आम तौर पर उपज वापसी का उपयोग apear एक संग्रह, उदा .:

public IEnumerable<Thing> GetThings() 
{ 
    yield return GetNextThing(); 
} 
+1

सिवाय इसके कि यूनिटी 3 डी इंजन उस आईन्यूमेरेटर का उपयोग करने वाला एकमात्र है, और उस इंजन को इसे एक आईनेमरेबल होने की आवश्यकता है। कोई तर्क दे सकता है कि IEnumrable बेहतर है, लेकिन किसी को भी Unity3d द्वारा डिज़ाइन किए गए डिज़ाइन के साथ खेलना होगा। – Sjoerd