paint-brush
ইউনিটি 2023.1 প্রতীক্ষিত ক্লাস প্রবর্তন করেদ্বারা@deniskondratev
7,136 পড়া
7,136 পড়া

ইউনিটি 2023.1 প্রতীক্ষিত ক্লাস প্রবর্তন করে

দ্বারা Denis Kondratev10m2023/01/27
Read on Terminal Reader
Read this story w/o Javascript

অতিদীর্ঘ; পড়তে

নিবন্ধটি ইউনিটি 2023.1-এ প্রবর্তিত নতুন প্রতীক্ষিত ক্লাস নিয়ে আলোচনা করেছে, যা ইউনিটি গেম ডেভেলপমেন্টে অ্যাসিঙ্ক্রোনাস কোড লেখার জন্য আরও সুযোগের অনুমতি দেয়। এটি অপেক্ষার পদ্ধতি, অ্যাসিঙ্ক্রোনাস এক্সিকিউশন বন্ধ করার বৈশিষ্ট্য এবং অন্যান্য ইউনিটি টুল যেমন Coroutines এবং InvokeRepeating এর সাথে ব্যবহার কভার করে। এটি অ্যাসিঙ্ক-অপেক্ষার মূল বিষয়গুলি বোঝার এবং এর ক্ষমতা এবং সীমাবদ্ধতাগুলি বোঝার জন্য অপেক্ষাযোগ্য শ্রেণীর সাথে পরীক্ষা করার গুরুত্বের উপর জোর দেয়।
featured image - ইউনিটি 2023.1 প্রতীক্ষিত ক্লাস প্রবর্তন করে
Denis Kondratev HackerNoon profile picture
0-item

2022 সালের মে মাসে, আলেকজান্ডার মুটেল এবং ক্রিস্টিনা হাউগার্ড তাদের পোস্টে ঘোষণা করেছিলেন "ইউনিটি এবং .নেট, এর পরে কী?" যে ইউনিটি .NET-এর আরও বৈশিষ্ট্য গ্রহণ করার পরিকল্পনা করেছে, যার মধ্যে async-await ব্যবহারের সুবিধা রয়েছে। এবং, মনে হচ্ছে ঐক্য তার প্রতিশ্রুতি অনুসরণ করছে। ইউনিটি 2023.1 আলফা সংস্করণে, প্রতীক্ষিত ক্লাস চালু করা হয়েছে, যা অ্যাসিঙ্ক্রোনাস কোড লেখার জন্য আরও সুযোগ প্রদান করে।

অপেক্ষার পদ্ধতি

এই বিভাগে, আমি এমন পদ্ধতিগুলির মধ্যে খুব গভীরভাবে অনুসন্ধান করব না যা, আমার মতে, অফিসিয়াল ইউনিটি ডকুমেন্টেশনে পর্যাপ্ত বিবরণ রয়েছে। এগুলি সবই অ্যাসিঙ্ক্রোনাস অপেক্ষার সাথে সম্পর্কিত।


Awaitable.WaitForSecondsAsync() আপনাকে খেলার নির্দিষ্ট সময়ের জন্য অপেক্ষা করতে দেয়। Task.Delay() এর বিপরীতে, যা রিয়েল-টাইমে অপেক্ষা করে। পার্থক্য স্পষ্ট করতে সাহায্য করার জন্য, আমি পরে একটি কোড ব্লকে একটি ছোট উদাহরণ প্রদান করব।


 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."); }


এই উদাহরণে, Start() পদ্ধতির শুরুতে, Time.timeScale ব্যবহার করে খেলার সময় বন্ধ করা হয়। পরীক্ষার খাতিরে, RunGameplay() পদ্ধতিতে 5 সেকেন্ড পরে তার প্রবাহ পুনরায় শুরু করতে একটি Coroutine ব্যবহার করা হবে। তারপর, আমরা দুটি এক-সেকেন্ডের অপেক্ষার পদ্ধতি চালু করি। একটি Awaitable.WaitForSecondsAsync() ব্যবহার করে এবং অন্যটি Task.Delay() ব্যবহার করে। এক সেকেন্ড পরে, আমরা কনসোলে একটি বার্তা পাব "Waiting WaitWithTaskDelay() ended"। এবং 5 সেকেন্ড পর, "Waiting WaitWithTaskDelay() ended" মেসেজ আসবে।


ইউনিটির বেসিক প্লেয়ার লুপে আপনাকে আরও নমনীয়তা দেওয়ার জন্য অন্যান্য সুবিধাজনক পদ্ধতিগুলিও যুক্ত করা হয়েছে। তাদের উদ্দেশ্য নাম থেকে পরিষ্কার এবং Coroutines ব্যবহার করার সময় তাদের সাদৃশ্যের সাথে মিলে যায়:


  • EndOfFrameAsync()
  • FixedUpdateAsync()
  • NextFrameAsync()


আপনি যদি Coroutines-এর সাথে কাজ করার জন্য নতুন হয়ে থাকেন, তাহলে আরও ভাল বোঝার জন্য আমি নিজে থেকে সেগুলি নিয়ে পরীক্ষা করার পরামর্শ দিই।


একটি পদ্ধতি, Awaitable.FromAsyncOperation(), পুরানো API, AsyncOperation-এর সাথে পশ্চাদপদ সামঞ্জস্যের জন্যও যোগ করা হয়েছে।

DestroyCancellationToken সম্পত্তি ব্যবহার করে

Coroutines ব্যবহার করার সুবিধার মধ্যে একটি হল যে উপাদানটি সরানো বা অক্ষম করা হলে তারা স্বয়ংক্রিয়ভাবে বন্ধ হয়ে যায়। ইউনিটি 2022.2-এ, DestroCancellationToken প্রপার্টি MonoBehaviour-এ যোগ করা হয়েছিল, যা আপনাকে অবজেক্ট ডিলিট করার সময় অ্যাসিঙ্ক্রোনাস এক্সিকিউশন বন্ধ করতে দেয়। এটা মনে রাখা গুরুত্বপূর্ণ যে CancellationToken বাতিলকরণের মাধ্যমে কাজটি বন্ধ করা 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); }


এই উদাহরণে, অবজেক্টটি অবিলম্বে Start() এ ধ্বংস হয়ে গেছে, কিন্তু তার আগে, Awake() DoAwaitAsync() এর এক্সিকিউশন চালু করতে পরিচালনা করে। Awaitable.WaitForSecondsAsync(1, DestroyCancellationToken) কমান্ডটি 1 সেকেন্ডের জন্য অপেক্ষা করে এবং তারপর বার্তাটি আউটপুট করা উচিত "এই বার্তাটি লগ করা হবে না।" কারণ অবজেক্টটি অবিলম্বে মুছে ফেলা হয়, DestroCancellationToken OperationCanceledException নিক্ষেপ করে পুরো চেইনের সম্পাদন বন্ধ করে দেয়। এইভাবে, DestroCancellationToken আমাদেরকে ম্যানুয়ালি একটি CancellationToken তৈরি করার প্রয়োজন থেকে মুক্তি দেয়।


কিন্তু আমরা এখনও এটি করতে পারি, উদাহরণস্বরূপ, বস্তু নিষ্ক্রিয় করার সময় মৃত্যুদন্ড বন্ধ করতে। আমি একটি উদাহরণ দেব।


 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() যা আপনাকে অনুরূপ কাজগুলি আরও সহজে সম্পাদন করতে দেয়। কিন্তু এটি ব্যবহারের একটি উদাহরণ মাত্র। এখানে আমরা শুধু অপেক্ষাযোগ্য নিয়ে কাজ করছি।


Application.exitCancellationToken প্রপার্টি ব্যবহার করা

ইউনিটিতে, এডিটরে প্লে মোড থেকে বেরিয়ে আসার পরেও অ্যাসিঙ্ক মেথড এক্সিকিউশন নিজে থেকে বন্ধ হয় না। প্রকল্পে একটি অনুরূপ স্ক্রিপ্ট যোগ করা যাক.


 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 ব্যবহার করতে পারি, যা প্লে মোড থেকে প্রস্থান করার পরে অ্যাসিঙ্ক পদ্ধতির সম্পাদনে বাধা দেয়। স্ক্রিপ্ট ঠিক করা যাক.


 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 হতে পারে, উদাহরণস্বরূপ, Start, 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


এটিও মনে রাখা দরকার যে অ্যাসিঙ্ক্রোনাস কোডটি এখনও কার্যকর করার সময় MonoBehaviour নিজেই বা এমনকি গেম অবজেক্টটি অস্তিত্ব বন্ধ করে দিতে পারে। এমন পরিস্থিতিতে:


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


পরবর্তী ফ্রেমে, MonoBehaviour মুছে ফেলা হয়েছে বলে মনে করা হয়। কনসোলে, আমরা নিম্নলিখিত ফলাফল পাব:


 True Flase


এটি OnDestroy() পদ্ধতিতেও প্রযোজ্য। আপনি যদি পদ্ধতিটিকে অ্যাসিঙ্ক্রোনাস করেন, তাহলে আপনার বিবেচনা করা উচিত যে ওয়েট স্টেটমেন্টের পরে, MonoBehaviour ইতিমধ্যেই মুছে ফেলা হয়েছে বলে মনে করা হয়েছে। যখন বস্তুটি নিজেই মুছে ফেলা হয়, তখন এটিতে অবস্থিত অনেক MonoBehaviours এর কাজ এই সময়ে সঠিকভাবে কাজ নাও করতে পারে।


এটি লক্ষণীয় যে ইভেন্ট ফাংশনগুলির সাথে কাজ করার সময়, কার্যকর করার ক্রম সম্পর্কে সচেতন হওয়া গুরুত্বপূর্ণ। অ্যাসিঙ্ক্রোনাস কোড আপনার প্রত্যাশা অনুযায়ী কার্যকর নাও হতে পারে এবং আপনার স্ক্রিপ্ট ডিজাইন করার সময় এটি মনে রাখা অপরিহার্য।

প্রতীক্ষিত ইভেন্ট ফাংশন সব ধরনের ব্যতিক্রম ধরা

এটা লক্ষণীয় যে প্রতীক্ষিত ইভেন্ট ফাংশন সব ধরনের ব্যতিক্রম ধরতে পারে, যা অপ্রত্যাশিত হতে পারে। আমি আশা করছিলাম যে তারা শুধুমাত্র OperationCanceledExceptions ধরবে, যা আরও বোধগম্য হবে। কিন্তু সব ধরনের ব্যতিক্রম ধরা তাদের এই সময়ে ব্যবহারের উপযোগী করে তোলে না। পরিবর্তে, আপনি অ্যাসিঙ্ক পদ্ধতি চালাতে পারেন এবং ম্যানুয়ালি প্রয়োজনীয় বার্তাগুলি ধরতে পারেন, যেমনটি আগের উদাহরণে দেখানো হয়েছে।


 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() ধরা হয়েছে, অন্য সব ব্যতিক্রম নিক্ষেপ করা যেতে পারে।


আমি আশা করি ভবিষ্যতে এই পদ্ধতিটি সংশোধন করা হবে। এই মুহুর্তে, প্রতীক্ষিত ইভেন্ট ফাংশনগুলির ব্যবহার নিরাপদ নয়৷

থ্রেড জুড়ে বিনামূল্যে আন্দোলন

হিসাবে পরিচিত, গেম অবজেক্ট এবং MonoBehaviours সঙ্গে সমস্ত অপারেশন শুধুমাত্র প্রধান থ্রেড অনুমোদিত হয়. কখনও কখনও এটি ব্যাপক গণনা করা প্রয়োজন যা গেম হিমায়িত হতে পারে। মূল থ্রেডের বাইরে এগুলি সম্পাদন করা ভাল। প্রতীক্ষিত দুটি পদ্ধতি অফার করে, 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 বৈশিষ্ট্যগুলি অবজেক্ট মুছে ফেলার সময় বা প্লে মোড থেকে প্রস্থান করার সময় অ্যাসিঙ্ক্রোনাস এক্সিকিউশন বন্ধ করার একটি সুবিধাজনক উপায় প্রদান করে।


এটি লক্ষ করা গুরুত্বপূর্ণ যে অপেক্ষাযোগ্য ক্লাস ইউনিটিতে অ্যাসিঙ্ক্রোনাস কোড লেখার একটি নতুন উপায় সরবরাহ করে, এটি সেরা ফলাফল অর্জনের জন্য অন্যান্য ইউনিটি সরঞ্জাম যেমন Coroutines এবং InvokeRepeating এর সাথে একত্রে ব্যবহার করা উচিত। অতিরিক্তভাবে, async-await এর মূল বিষয়গুলি এবং এটি গেম ডেভেলপমেন্ট প্রক্রিয়াতে যে সুবিধাগুলি আনতে পারে, যেমন পারফরম্যান্স এবং প্রতিক্রিয়াশীলতা উন্নত করা যায় তা বোঝা গুরুত্বপূর্ণ।


সংক্ষেপে, প্রতীক্ষিত শ্রেণীটি ইউনিটি ডেভেলপারদের জন্য একটি শক্তিশালী হাতিয়ার, তবে এটি সর্বোত্তম ফলাফল অর্জনের জন্য যত্ন সহকারে এবং অন্যান্য ইউনিটি সরঞ্জাম এবং ধারণার সাথে একত্রে ব্যবহার করা উচিত। এর ক্ষমতা এবং সীমাবদ্ধতাগুলি আরও ভালভাবে বোঝার জন্য এটি নিয়ে পরীক্ষা করা গুরুত্বপূর্ণ।