paint-brush
एकता 2023.1 प्रतीक्षा योग्य वर्ग का परिचय देती हैद्वारा@deniskondratev
7,136 रीडिंग
7,136 रीडिंग

एकता 2023.1 प्रतीक्षा योग्य वर्ग का परिचय देती है

द्वारा Denis Kondratev10m2023/01/27
Read on Terminal Reader

बहुत लंबा; पढ़ने के लिए

लेख एकता 2023.1 में पेश किए गए नए प्रतीक्षित वर्ग पर चर्चा करता है, जो एकता खेल के विकास में अतुल्यकालिक कोड लिखने के अधिक अवसरों की अनुमति देता है। इसमें वेटिंग मेथड, एसिंक्रोनस एक्जीक्यूशन को रोकने के लिए गुण, और अन्य यूनिटी टूल्स जैसे कॉरआउट्स और इनवोकरिपीटिंग के साथ उपयोग शामिल हैं। यह async-wait की मूल बातें समझने और इसकी क्षमताओं और सीमाओं को समझने के लिए Awaitable वर्ग के साथ प्रयोग करने के महत्व पर जोर देता है।
featured image - एकता 2023.1 प्रतीक्षा योग्य वर्ग का परिचय देती है
Denis Kondratev HackerNoon profile picture
0-item

मई 2022 में, एलेक्जेंडर मुटेल और क्रिस्टीना हौगार्ड ने अपने पोस्ट "यूनिटी एंड .NET, व्हाट्स नेक्स्ट?" कि यूनिटी .NET की और अधिक विशेषताओं को अपनाने की योजना बना रही है, जिसमें async-wait का उपयोग करने की सुविधा भी शामिल है। और, ऐसा लगता है कि एकता अपने वादे पर चल रही है। एकता 2023.1 अल्फा संस्करण में, अतुल्यकालिक कोड लिखने के लिए अधिक अवसर प्रदान करते हुए, प्रतीक्षा योग्य वर्ग पेश किया गया है।

प्रतीक्षा के तरीके

इस खंड में, मैं उन तरीकों में बहुत गहराई से नहीं जाऊंगा, जो मेरी राय में आधिकारिक एकता दस्तावेज में पर्याप्त विवरण हैं। वे सभी अतुल्यकालिक प्रतीक्षा से संबंधित हैं।


Awaitable.WaitForSecondsAsync() आपको एक निर्दिष्ट समय के लिए प्रतीक्षा करने की अनुमति देता है। टास्क के विपरीत। विलंब (), जो वास्तविक समय में प्रतीक्षा करता है। अंतर को स्पष्ट करने में सहायता के लिए, मैं बाद में कोड ब्लॉक में एक छोटा सा उदाहरण प्रदान करूंगा।


 private void Start() { Time.timeScale = 0; StartCoroutine(RunGameplay()); Task.WhenAll( WaitWithWaitForSecondsAsync(), WaitWithTaskDelay()); } private IEnumerator RunGameplay() { yield return new WaitForSecondsRealtime(5); Time.timeScale = 1; } private async Task WaitWithWaitForSecondsAsync() { await Awaitable.WaitForSecondsAsync(1); Debug.Log("Waiting WithWaitForSecondsAsync() ended."); } private async Task WaitWithTaskDelay() { await Task.Delay(1); Debug.Log("Waiting WaitWithTaskDelay() ended."); }


इस उदाहरण में, प्रारंभ () पद्धति की शुरुआत में, Time.timeScale का उपयोग करके खेल का समय रोक दिया जाता है। प्रयोग के लिए, रनगेमप्ले () पद्धति में 5 सेकंड के बाद अपने प्रवाह को फिर से शुरू करने के लिए एक कोरूटिन का उपयोग किया जाएगा। फिर, हम दो एक-सेकंड की प्रतीक्षा विधियाँ लॉन्च करते हैं। एक Awaitable.WaitForSecondsAsync() का उपयोग कर रहा है, और दूसरा Task.Delay() का उपयोग कर रहा है। एक सेकंड के बाद, हमें कंसोल में एक संदेश प्राप्त होगा "वेटिंग वेटविथटास्कडेले () समाप्त"। और 5 सेकंड के बाद, "वेटिंग वेटविथटास्कडेले () समाप्त" संदेश दिखाई देगा।


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


  • EndOfFrameAsync()
  • फिक्स्डअपडेटएसिंक ()
  • नेक्स्टफ्रेमएसिंक ()


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


पुराने API, AsyncOperation के साथ पश्च संगतता के लिए Awaitable.FromAsyncOperation(), एक विधि भी जोड़ी गई है।

नष्ट रद्दीकरण टोकन संपत्ति का उपयोग करना

Coroutines का उपयोग करने की एक सुविधा यह है कि यदि घटक हटा दिया जाता है या अक्षम कर दिया जाता है तो वे स्वचालित रूप से बंद हो जाते हैं। एकता 2022.2 में, नष्ट रद्दीकरण टोकन संपत्ति को मोनोबिहेवियर में जोड़ा गया था, जिससे आप ऑब्जेक्ट विलोपन के समय अतुल्यकालिक निष्पादन को रोक सकते हैं। यह याद रखना महत्वपूर्ण है कि रद्दीकरण टोकन रद्दीकरण के माध्यम से कार्य को रोकना OperationCanceledException को फेंकता है। यदि कॉलिंग विधि टास्क या प्रतीक्षा योग्य नहीं लौटाती है, तो यह अपवाद पकड़ा जाना चाहिए।


 private async void Awake() { try { await DoAwaitAsync(); } catch (OperationCanceledException) { } } private async Awaitable DoAwaitAsync() { await Awaitable.WaitForSecondsAsync(1, destroyCancellationToken); Debug.Log("That message won't be logged."); } private void Start() { Destroy(this); }


इस उदाहरण में, ऑब्जेक्ट तुरंत स्टार्ट () में नष्ट हो जाता है, लेकिन इससे पहले, अवेक () DoAwaitAsync () के निष्पादन को लॉन्च करने का प्रबंधन करता है। आदेश प्रतीक्षा योग्य। क्योंकि वस्तु तुरंत हटा दी जाती है, DestroyCancellationToken OperationCanceledException को फेंक कर पूरी श्रृंखला के निष्पादन को रोक देता है। इस तरह, नष्ट रद्दीकरण टोकन हमें मैन्युअल रूप से रद्दीकरण टोकन बनाने की आवश्यकता से राहत देता है।


लेकिन हम अभी भी ऐसा कर सकते हैं, उदाहरण के लिए, वस्तु के निष्क्रिय होने के समय निष्पादन को रोकने के लिए। मैं एक उदाहरण दूंगा।


 using System; using System.Threading; using UnityEngine; public class Example : MonoBehaviour { private CancellationTokenSource _tokenSource; private async void OnEnable() { _tokenSource = new CancellationTokenSource(); try { await DoAwaitAsync(_tokenSource.Token); } catch (OperationCanceledException) { } } private void OnDisable() { _tokenSource.Cancel(); _tokenSource.Dispose(); } private static async Awaitable DoAwaitAsync(CancellationToken token) { while (!token.IsCancellationRequested) { await Awaitable.WaitForSecondsAsync(1, token); Debug.Log("This message is logged every second."); } } }


इस रूप में, संदेश "यह संदेश हर सेकंड लॉग किया जाता है" तब तक भेजा जाएगा जब तक कि जिस वस्तु पर यह मोनोबिहेवियर लटका हुआ है, वह चालू है। वस्तु को बंद करके फिर से चालू किया जा सकता है।


यह कोड बेमानी लग सकता है। एकता में पहले से ही कई सुविधाजनक उपकरण हैं जैसे कि Coroutines और InvokeRepeating () जो आपको समान कार्यों को बहुत आसान करने की अनुमति देते हैं। लेकिन यह सिर्फ प्रयोग का एक उदाहरण है। यहाँ हम केवल Awaitable के साथ काम कर रहे हैं।


Application.exitCancellationToken संपत्ति का उपयोग करना

एकता में, संपादक में प्ले मोड से बाहर निकलने के बाद भी async विधि का निष्पादन अपने आप नहीं रुकता है। आइए प्रोजेक्ट में एक समान स्क्रिप्ट जोड़ें।


 using System.Threading.Tasks; using UnityEngine; public static class Boot { [RuntimeInitializeOnLoadMethod] public static async Awaitable LogAsync() { while (true) { Debug.Log("This message is logged every second."); await Task.Delay(1000); } } }


इस उदाहरण में, प्ले मोड में स्विच करने के बाद, "यह संदेश हर सेकंड लॉग होता है" संदेश कंसोल पर आउटपुट होगा। प्ले बटन जारी होने के बाद भी यह आउटपुट बना रहता है। इस उदाहरण में, Awaitable.WaitForSecondsAsync() के बजाय Task.Delay() का उपयोग किया जाता है, क्योंकि यहां, कार्रवाई दिखाने के लिए, खेल के समय में नहीं बल्कि वास्तविक समय में देरी की आवश्यकता होती है।


समान रूप से रद्दीकरण टोकन को नष्ट करने के लिए, हम Application.exitCancellationToken का उपयोग कर सकते हैं, जो प्ले मोड से बाहर निकलने पर async विधियों के निष्पादन को बाधित करता है। आइए स्क्रिप्ट को ठीक करें।


 using System.Threading.Tasks; using UnityEngine; public static class Boot { [RuntimeInitializeOnLoadMethod] public static async Awaitable LogAsync() { var cancellationToken = Application.exitCancellationToken; while (!cancellationToken.IsCancellationRequested) { Debug.Log("This message is logged every second."); await Task.Delay(1000, cancellationToken); } } }


अब स्क्रिप्ट इरादे के अनुसार निष्पादित होगी।

इवेंट फ़ंक्शंस के साथ प्रयोग करना

एकता में, कुछ ईवेंट फ़ंक्शन Coroutines हो सकते हैं, उदाहरण के लिए, प्रारंभ करें, OnCollisionEnter, या OnCollisionExit। लेकिन एकता 2023.1 से शुरू होकर, वे सभी प्रतीक्षा योग्य हो सकते हैं, जिसमें अपडेट (), लेटअपडेट और यहां तक कि ऑनडेस्ट्रॉय () शामिल हैं।


उनका उपयोग सावधानी के साथ किया जाना चाहिए, क्योंकि उनके अतुल्यकालिक निष्पादन के लिए कोई प्रतीक्षा नहीं है। उदाहरण के लिए, निम्नलिखित कोड के लिए:


 private async Awaitable Awake() { Debug.Log("Awake() started"); await Awaitable.NextFrameAsync(); Debug.Log("Awake() finished"); } private void OnEnable() { Debug.Log("OnEnable()"); } private void Start() { Debug.Log("Start()"); }


कंसोल में, हम निम्नलिखित परिणाम प्राप्त करेंगे:


 Awake() started OnEnable() Start() Awake() finished


यह भी याद रखने योग्य है कि एसिंक्रोनस कोड अभी भी निष्पादित होने पर मोनोबिहेवियर स्वयं या यहां तक कि गेम ऑब्जेक्ट अस्तित्व में नहीं रह सकता है। ऐसी स्थिति में:


 private async Awaitable Awake() { Debug.Log(this != null); await Awaitable.NextFrameAsync(); Debug.Log(this != null); } private void Start() { Destroy(this); }


अगले फ्रेम में, मोनोबिहेवियर को हटा दिया गया माना जाता है। कंसोल में, हम निम्नलिखित परिणाम प्राप्त करेंगे:


 True Flase


यह ऑनडेस्ट्रॉय () पद्धति पर भी लागू होता है। यदि आप विधि को अतुल्यकालिक बनाते हैं, तो आपको यह ध्यान रखना चाहिए कि प्रतीक्षित कथन के बाद, MonoBehaviour को पहले ही हटा दिया गया माना जाता है। जब ऑब्जेक्ट स्वयं हटा दिया जाता है, तो उस पर स्थित कई मोनोबिहेवियर्स का काम इस बिंदु पर ठीक से काम नहीं कर सकता है।


यह ध्यान देने योग्य है कि ईवेंट फ़ंक्शंस के साथ काम करते समय, निष्पादन के क्रम से अवगत होना महत्वपूर्ण है। एसिंक्रोनस कोड आपके द्वारा अपेक्षित क्रम में निष्पादित नहीं हो सकता है, और अपनी स्क्रिप्ट डिज़ाइन करते समय इसे ध्यान में रखना आवश्यक है।

प्रतीक्षित ईवेंट फ़ंक्शंस सभी प्रकार के अपवादों को पकड़ते हैं

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


 private async void Awake() { try { await DoAwaitAsync(); } catch (OperationCanceledException) { } } private async Awaitable DoAwaitAsync() { await Awaitable.WaitForSecondsAsync(1, destroyCancellationToken); Debug.Log("That message won't be logged"); } private void Start() { Destroy(this); }


क्योंकि घटक शुरू होने पर तुरंत हटा दिया जाता है, DoAwaitAsync() का निष्पादन बाधित हो जाएगा। संदेश "वह संदेश लॉग नहीं किया जाएगा" कंसोल में दिखाई नहीं देगा। केवल OperationCanceledException() पकड़ा गया है, अन्य सभी अपवादों को फेंका जा सकता है।


मुझे उम्मीद है कि भविष्य में इस दृष्टिकोण को सुधारा जाएगा। फिलहाल, Awaitable Event Functions का इस्तेमाल सुरक्षित नहीं है।

थ्रेड्स में फ्री मूवमेंट

जैसा कि जाना जाता है, खेल वस्तुओं और मोनोबिहेवियर्स के साथ सभी संचालन केवल मुख्य धागे में ही अनुमति है। कभी-कभी बड़े पैमाने पर गणना करना आवश्यक होता है जिससे गेम फ्रीज हो सकता है। मुख्य धागे के बाहर उन्हें प्रदर्शन करना बेहतर होता है। Awaitable दो तरीके प्रदान करता है, BackgroundThreadAsync () और MainThreadAsync (), जो मुख्य थ्रेड से दूर जाने और उस पर लौटने की अनुमति देता है। मैं एक उदाहरण दूंगा।


 private async Awaitable DoAwaitAsync(CancellationToken token) { await Awaitable.BackgroundThreadAsync(); Debug.Log($"Thread: {Thread.CurrentThread.ManagedThreadId}"); Thread.Sleep(10000); await Awaitable.MainThreadAsync(); if (token.IsCancellationRequested) { return; } Debug.Log($"Thread: {Thread.CurrentThread.ManagedThreadId}"); gameObject.SetActive(false); await Awaitable.BackgroundThreadAsync(); Debug.Log($"Thread: {Thread.CurrentThread.ManagedThreadId}"); }


यहां, जब विधि शुरू होती है, तो यह एक अतिरिक्त थ्रेड पर स्विच हो जाएगी। यहां मैं इस अतिरिक्त थ्रेड की आईडी को कंसोल पर आउटपुट करता हूं। यह 1 के बराबर नहीं होगा, क्योंकि 1 मुख्य धागा है।


फिर थ्रेड 10 सेकंड के लिए जम जाता है (Thread.Sleep(10000)), बड़े पैमाने पर गणनाओं का अनुकरण करता है। यदि आप इसे मुख्य थ्रेड में करते हैं, तो खेल इसके निष्पादन की अवधि के लिए फ्रीज होता हुआ दिखाई देगा। लेकिन इस स्थिति में सब कुछ स्थिर रूप से काम करता रहता है। अनावश्यक ऑपरेशन को रोकने के लिए आप इन गणनाओं में रद्दीकरण टोकन का भी उपयोग कर सकते हैं।


उसके बाद, हम मुख्य थ्रेड पर वापस जाते हैं। और अब सभी एकता कार्य हमारे लिए फिर से उपलब्ध हैं। उदाहरण के लिए, जैसा कि इस मामले में, गेम ऑब्जेक्ट को अक्षम करना, जो कि मुख्य थ्रेड के बिना करना संभव नहीं था।

निष्कर्ष

अंत में, यूनिटी 2023.1 में पेश किया गया नया अवेटेबल क्लास डेवलपर्स को अतुल्यकालिक कोड लिखने के अधिक अवसर प्रदान करता है, जिससे उत्तरदायी और प्रदर्शनकारी गेम बनाना आसान हो जाता है। प्रतीक्षा योग्य वर्ग में विभिन्न प्रकार की प्रतीक्षा विधियाँ शामिल हैं, जैसे WaitForSecondsAsync(), EndOfFrameAsync(), FixedUpdateAsync(), और NextFrameAsync(), जो एकता के मूल प्लेयर लूप में अधिक लचीलेपन की अनुमति देती हैं। DestroyCancellationToken और Application.exitCancellationToken विशेषताएँ वस्तु को हटाने या प्ले मोड से बाहर निकलने के समय अतुल्यकालिक निष्पादन को रोकने का एक सुविधाजनक तरीका भी प्रदान करती हैं।


यह ध्यान रखना महत्वपूर्ण है कि जब प्रतीक्षा योग्य वर्ग एकता में अतुल्यकालिक कोड लिखने का एक नया तरीका प्रदान करता है, तो इसका उपयोग अन्य एकता उपकरणों जैसे कि कॉरटीन्स और इनवोकरिपीटिंग के साथ सर्वोत्तम परिणाम प्राप्त करने के लिए किया जाना चाहिए। इसके अतिरिक्त, async-wait की मूल बातों को समझना महत्वपूर्ण है और इससे खेल विकास प्रक्रिया में लाभ हो सकता है, जैसे प्रदर्शन और जवाबदेही में सुधार।


संक्षेप में, प्रतीक्षा योग्य वर्ग एकता डेवलपर्स के लिए एक शक्तिशाली उपकरण है, लेकिन इसे सर्वोत्तम परिणाम प्राप्त करने के लिए देखभाल और अन्य एकता उपकरणों और अवधारणाओं के संयोजन के साथ उपयोग किया जाना चाहिए। इसकी क्षमताओं और सीमाओं को बेहतर ढंग से समझने के लिए इसके साथ प्रयोग करना महत्वपूर्ण है।