यूनिटी 3 डी गेम इंजन के 'यील्ड रिटर्न www' में अंतर्निहित तंत्र


14

यूनिटी 3 डी गेम इंजन में, रिमोट डेटा प्राप्त करने के लिए एक समान कोड अनुक्रम यह है:

WWW www = new WWW("http://remote.com/data/location/with/texture.png");
yield return www;

यहाँ अंतर्निहित तंत्र क्या है?

मुझे पता है कि हम अगले फ्रेम को संसाधित करने की अनुमति देने के लिए उपज तंत्र का उपयोग करते हैं, जबकि डाउनलोड पूरा हो रहा है। लेकिन जब हम करते हैं, तो हुड के नीचे क्या चल रहा है yield return www?

क्या विधि कहा जा रहा है (यदि कोई हो, डब्ल्यूडब्ल्यूडब्ल्यू वर्ग पर)? क्या धागे का उपयोग एकता है? क्या "ऊपरी" एकता परत www उदाहरण से पकड़ कर कुछ कर रही है?

संपादित करें:

  • यह प्रश्न विशेष रूप से यूनिटी 3 डी इंटर्नल के बारे में है। yieldC # में कथन कैसे काम करता है, इसके स्पष्टीकरण में मुझे कोई दिलचस्पी नहीं है। इसके बजाय, मैं अंदर के दृश्य की तलाश कर रहा हूं कि एकता इन निर्माणों से कैसे निपटती है, उदाहरण के लिए, कई फ्रेम में वितरित तरीके से डब्ल्यूडब्ल्यूडब्ल्यू को डेटा के एक टुकड़े को डाउनलोड करने के लिए।

1
ध्यान दें कि yield returnअतुल्यकालिक संचालन के लिए उपयोग करना एक हैक है। "वास्तविक" C # प्रोग्राम में, आप इसके लिए उपयोग करेंगे Task। एकता शायद उनका उपयोग नहीं कर रही है क्योंकि इसे पहले बनाया गया था। नेट 4.0, जब Taskपेश किया गया था।
ब्लूराजा - डैनी पफ्लुगुफ्ट

जवाबों:


8

यह कार्रवाई में C # उपज कीवर्ड है - यह wwwऑब्जेक्ट के साथ कुछ विशेष नहीं कर रहा है , बल्कि इसका मतलब है कि इसमें निहित विधि के लिए कुछ विशेष है। विशेष रूप से इस कीवर्ड का उपयोग केवल उस विधि में किया जा सकता है जो IEnumerable(या IEnumerator) वापस लौटाता है , और इसका उपयोग किया जाता है। इस बात को इंगित करने के लिए कि MoveNext को कहा जाता है , तो एन्यूमरेटर द्वारा किस वस्तु को "वापस" किया जाएगा ।

यह काम करता है क्योंकि कंपाइलर पूरी विधि को एक अलग वर्ग में परिवर्तित करता है जो राज्य मशीन का उपयोग करके IEnumerable(या IEnumerator) लागू करता है - शुद्ध परिणाम यह है कि विधि का शरीर तब तक निष्पादित नहीं होता है जब तक कि कोई रिटर्न वैल्यू के माध्यम से गणना नहीं करता है। यह किसी भी प्रकार के साथ काम करेगा WWW, इसके बारे में कुछ भी विशेष नहीं है , बल्कि इसकी विधि है जो विशेष है।

C # कंपाइलर कोड के किस प्रकार के लिए C # यील्ड कीवर्ड के दृश्यों के पीछे एक नज़र डालें, C # कंपाइलर किस तरह का उत्पन्न होता है, या केवल IL जासूस जैसी किसी चीज़ का उपयोग करके कोड का स्वयं प्रयोग और निरीक्षण करते हैं


अपडेट: स्पष्ट करने के लिए

  • जब एकता ने एक कोरटाइन को कॉल किया, जिसमें एक yield returnबयान होता है, जो यह है कि एक एन्यूमरेटर लौटाया जाता है - इस बिंदु पर किसी भी विधि निकाय को निष्पादित नहीं किया जाता है
  • MoveNextअनुक्रम को पहला मान प्राप्त करने के लिए एकता को निष्पादित करने के लिए विधि निकाय को प्राप्त करने के लिए एकता पर कॉल करना होगा । यह विधि को पहले yeild returnकथन तक निष्पादित करने का कारण बनता है , जिस बिंदु पर कॉलर फिर से शुरू होता है (और संभवतः एकता बाकी फ्रेम को प्रस्तुत करने के लिए जाती है)
  • जैसा कि मैं इसे एकता को सामान्य रूप से समझता हूं तो कॉल करने के लिए आगे बढ़ता है MoveNext प्रत्येक बाद के फ्रेम में एक बार इट्रेटर पर विधि , जिससे विधि अगले yield returnफ्रेम में एक बार फिर से निष्पादित होती है , जब तक कि विधि का अंत या एक yield breakबयान तक नहीं पहुंच जाता है (संकेत करता है अनुक्रम का अंत)

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

बस स्पष्ट होने के लिए - yieldकीवर्ड कुछ विशेष नहीं करता हैWWW वर्ग के , बल्कि इसकी विशेष हैंडलिंग जो यूनिटी रिटर्न एन्यूमरेशन के सदस्यों को देती है जो इस व्यवहार का कारण बनती है।


दूसरा अपडेट करें:WWW वेब पेज डाउनलोड करने के लिए उपयोग करने वाले तंत्र के रूप में एसिंक्रोनस रूप से यह शायद HttpWebRequest.BeginGetResponse विधि का उपयोग करता है जो आंतरिक रूप से एसिंक्रोनस आईओ का उपयोग करेगा या वैकल्पिक रूप से यह थ्रेड्स का उपयोग कर सकता है (या तो एक समर्पित धागा बनाने या थ्रेड पूल का उपयोग करके)।


5
वास्तव में, एकता में, किसी WWWवस्तु के होने पर कुछ विशेष होता है , WWWसंदर्भ देखें
एरिक

9

yieldमुख्य रूप से एकता में एक coroutine संदर्भ में उपयोग किया जा रहा है। कोरटाइन के बारे में अधिक पढ़ने के लिए और वे C # का उपयोग क्यों करते हैं, yieldमैं इस ब्लॉग लेख की सिफारिश करता हूं: Unity3D coroutines विस्तार से । इस जवाब में अधिकांश शोध उस लेख से आता है।

एकता में Coroutines का उपयोग उन कार्यों को करने के लिए किया जाता है जो:

  1. प्रस्तुत किए जाने वाले फ्रेम से अधिक समय लग सकता है (जिससे मंदी हो सकती है), और
  2. गेम लूप से अलग से प्रदर्शन किया जा सकता है (क्योंकि परिणाम को वर्तमान फ्रेम के लिए उपलब्ध होने की आवश्यकता नहीं है)।

इस प्रकार के कार्यों के उदाहरण पथभेदी (पुनः) गणना हैं या, जैसा कि आपके प्रश्न में है, वेबसाइट से डेटा प्राप्त करना।

अपने अधीनताओं का उत्तर देने के लिए (थोड़े संशोधित क्रम में):

क्या विधि कहा जा रहा है (यदि कोई हो, डब्ल्यूडब्ल्यूडब्ल्यू वर्ग पर)? क्या "ऊपरी" एकता परत www उदाहरण से पकड़ कर कुछ कर रही है?

एकता की WWWकक्षा को एक कोरटाइन से उपजाने के लिए डिज़ाइन किया गया है। उपरोक्त लिंक किए गए ब्लॉग लेख पर टिप्पणियों के अनुसार, कोड के सट्टा ब्लॉक ('' ऊपरी '' परत) के बारे में YieldInstructionवास्तव में एक स्विच होता है जो उपज वाले WWWएस के लिए भी जांच करता है । इस कोड को तो यकीन है कि coroutine स्वचालित रूप से डाउनलोड, किया जाता है में वर्णित के रूप खत्म हो जाएगा बनाता WWWहै संदर्भ

क्या धागे का उपयोग एकता है?

इस मामले में, "बाकी गेम को अवरुद्ध किए बिना" डेटा डाउनलोड करने के लिए: हाँ, सबसे अधिक संभावना है। (और थ्रेडिंग निश्चित रूप से डाउनलोड किए गए डेटा को विघटित करने के लिए उपयोग किया जाता है, जैसा कि इसका सबूत है WWW.threadPriority।)


अच्छा! मैंने टिप्पणी देखी altdevblogaday.com/2011/07/07/unity3d-coroutines-in-detail/… और ऐसा लगता है कि डब्ल्यूडब्ल्यूडब्ल्यू विशेष रूप से व्यवहार किया जाता है। इसलिए मैं जानना चाहता हूं कि यह कैसे पूरा किया जाता है, ताकि थ्रेड्स का उपयोग किए बिना डाउनलोड को कई फ़्रेमों में बनाया जा सके?
तेन्द्रेकार्डसो

अच्छी बात! मुझे लगता है कि उस स्तर पर कुछ थ्रेडिंग चल रही होगी, आखिरकार, मैं उस परावर्तित करने के लिए अपने उत्तर को संपादित करूंगा।
एरिक

1
@thyandrecardoso मुझे लगता है कि यह HttpWebRequest.BeginGetResponse या इसी तरह का उपयोग करता है , हालांकि आप इस बात की पुष्टि करने के लिए असेंबली को विघटित कर सकते हैं अगर यह वास्तव में आपके लिए मायने रखता है।
जस्टिन

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

7

दुर्भाग्य से, डब्ल्यूडब्ल्यूडब्ल्यू को आंतरिक रूप से मूल कोड के रूप में लागू किया गया है, जिसका अर्थ है कि हम कोड को नहीं देख सकते हैं। प्रयोग से मैं ऐसा कह सकता हूं

  1. WWWसे व्युत्पन्न नहीं है YieldInstruction, इसलिए जो कुछ भी होता है जब आपको yieldविशेष-केस कोड द्वारा नियंत्रित किया जाना चाहिए।
  2. मैंने कभी कोई अंतर नहीं माना है

    yield return www;

    तथा

    while(!www.isDone)
        yield return null;

    मुझे लगता है कि इसे लागू करने का सबसे तार्किक तरीका है, और शायद यही वह है जो हुड के तहत चल रहा है। लेकिन मुझे यकीन नहीं है।

  3. एकता डाउनलोड करने के लिए एक नया सूत्र शुरू नहीं करता है , कम से कम कुछ प्लेटफार्मों (आईओएस, वेबप्लेयर) पर। या यदि यह करता है, तो यह WWW.isDoneमुख्य धागे पर सेट होता है। मुझे यह पता है क्योंकि यह कोड:

    while(!www.isDone)
        Thread.Sleep(500);

    काम नहीं करता है।

मुझे नहीं लगता कि आपके पास और अधिक विशिष्ट उत्तर हो सकते हैं जब तक कि यूनिटी 3 डी के स्रोत कोड तक पहुंच वाला कोई व्यक्ति यहां नहीं आता है।


हाँ। वास्तव में अच्छी अंतर्दृष्टि! धन्यवाद! भले ही प्रति थ्रेड लॉन्च नहीं हो रहा हो, लेकिन सबसे संभावित चीज जो डब्ल्यूडब्ल्यूडब्ल्यू (या इंजन लेयर) हो रही है, वह HttpWebRequest.BeginGetResponse (या ऐसा कुछ) का उपयोग करके ... सही है? कुछ पूरी तरह से async किसी भी तरह से होना चाहिए ... डाउनलोड "रोका" नहीं जा सकता।
तेन्द्रेकार्डसो

** फ्रेम के बीच "रोका" नहीं जा सकता, मेरा मतलब है।
तेरांड्रेकार्डसो

2

चूंकि Unity3D उनके स्क्रिप्टिंग इंजन के रूप में C # का उपयोग करता है इसलिए मुझे लगता है कि इसका मानक उपज कीवर्ड है जो C # में बनाया गया है। मूल रूप से इसका क्या अर्थ है कि यह www का मान पहले से ही लौटाता है ताकि आप इसे जारी रख सकें, जबकि अगली पुनरावृत्ति यह अगला मान लौटाएगा, आदि ... यील्ड मूल रूप से पृष्ठभूमि में एक राज्य मशीन और पुनरावृत्त बनाता है।


हां, मुझे लगता है कि मेरे पास उपज कीवर्ड के बारे में मूल धारणाएं हैं। हालांकि, डब्ल्यूडब्ल्यूडब्ल्यू के निर्माण के दौरान क्या हो रहा है जो उस "राज्य मशीन" के लिए अनुमति देता है? मेरा मतलब है, "यील्ड रिटर्न www" डब्ल्यूडब्ल्यूडब्ल्यू वर्ग के अंदर कुछ भी नहीं कह रहा है ... जब आप कहते हैं "इसका मतलब है कि यह www का मूल्य पहले से ही लौटाता है", www उदाहरण मूल्य क्या है? वह उदाहरण अगले "पुनरावृत्ति" पर क्या करेगा?
तेन्द्रेकार्डसो

1
यूनिटी कोरआउट्स में, डब्ल्यूडब्ल्यूडब्ल्यू की उपज एक विशेष मामला है, देखें WWWका संदर्भ । इसके अलावा, मुझे यकीन नहीं है कि yieldकुछ भी बनाता है। पुनरावृत्त IEnumerableप्रकार को लागू करने या इसका उपयोग रिटर्न प्रकार के रूप में किया जाता है। "राज्य मशीन" भी बंद लगता है। यकीन है, राज्य है, लेकिन अकेले एक पर्याप्त संपत्ति नहीं है, है ना? हो सकता है कि आप इस बारे में विस्तार से बता सकें।
एरिक

1
यहाँ सामान्य C # व्यवहार पर एक अच्छा संदर्भ दिया गया है। shadowcoding.blogspot.nl/2009/01/yield-and-c-state-machine.html । यील्ड का ट्रैक रखने के लिए बहुत सारे कोड उत्पन्न होते हैं, जहां वह पुनरावृत्ति करता है। डब्लूडब्लूडब्लू की उपज के विशेष मामले के बारे में, मुझे नहीं पता था, लेकिन डॉक्स के अनुसार इसमें सामान्य सी # कीवर्ड के साथ कुछ भी नहीं है, यह बहुत भ्रामक है, वे बस इसे एक async विधि बना सकते हैं।
रॉय टी।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.