Threadক্যে কীভাবে মূল থ্রেড জমা করবেন না?


33

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


1
আপনি পটভূমিতে অন্যান্য কাজ চালানোর জন্য থ্রেডিং সিস্টেমটি ব্যবহার করতে পারেন ... তবে তারা ইউনিটি এপিআই তে কিছু কল করতে পারে না কারণ স্টাফ থ্রেডসেফ নয়। কেবল মন্তব্য করছি কারণ আমি এটি করি নি এবং আত্মবিশ্বাসের সাথে আপনাকে উদাহরণ কোড দ্রুত দিতে পারছি না।
অলমো

Listমূল থ্রেডে আপনি যে ফাংশনগুলিতে কল করতে চান সেটি সঞ্চয় করতে ক্রিয়াগুলির ব্যবহার । লক করুন এবং অস্থায়ী তালিকার ফাংশনে Actionতালিকার অনুলিপি করুন Update, মূল তালিকাটি সাফ করুন তারপরে মূল থ্রেডের Actionমধ্যে কোডটি চালান Listute এটি করার জন্য আমার অন্যান্য পোস্ট থেকে ইউনিটিথ্রেড দেখুন । উদাহরণস্বরূপ, মূল থ্রেডে একটি ফাংশন কল করতে UnityThread.executeInUpdate(() => { transform.Rotate(new Vector3(0f, 90f, 0f)); });
প্রোগ্রামার

উত্তর:


48

আপডেট: 2018 এ, ইউনিটি একাধিক সিপিইউ কোর ব্যবহারের অফলোড এবং ব্যবহারের উপায় হিসাবে একটি সি # জব সিস্টেমটি চালু করছে

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

আমি ইঞ্জিনের বর্তমান অবস্থা প্রতিফলিত করে তাদের নিজস্ব উত্তর যুক্ত করার জন্য এই চাকরী সিস্টেমটি ব্যবহার করে অভিজ্ঞদের সাথে আমন্ত্রণ জানাব।


আমি অতীতে ইউনিটির হেভিওয়েট কাজের জন্য থ্রেডিং ব্যবহার করেছি (সাধারণত চিত্র এবং জ্যামিতি প্রক্রিয়াজাতকরণ), এবং দুটি সিভেট সহ অন্যান্য সি # অ্যাপ্লিকেশনগুলিতে থ্রেড ব্যবহার করা একেবারে আলাদা নয়:

  1. ইউনিটি .NET এর কিছুটা পুরনো সাবসেট ব্যবহার করে, এমন কিছু নতুন থ্রেডিং বৈশিষ্ট্য এবং লাইব্রেরি রয়েছে যা আমরা বাক্সের বাইরে ব্যবহার করতে পারি না, তবে বেসিকগুলি সেখানে রয়েছে।

  2. উপরে যেমন একটি মন্তব্যে অ্যালমো নোট করেছেন, অনেক ইউনিটির ধরণ থ্রেডসফ নয়, এবং যদি আপনি মূল থ্রেডটি নির্মাণ, ব্যবহার বা এমনকি তাদের তুলনা করার চেষ্টা করেন তবে ব্যতিক্রম ছুঁড়ে ফেলবেন। জিনিষ মনে রাখা:

    • একটি সাধারণ ক্ষেত্রে গেমঅজেক্ট বা মনোবিহাইওয়ের রেফারেন্সটি এর সদস্যদের অ্যাক্সেস করার চেষ্টা করার আগে বাতিল কিনা তা পরীক্ষা করে দেখা হচ্ছে। myUnityObject == nullইউনিটিইজাইন থেকে উত্পন্ন যে কোনও কিছুর জন্য একটি ওভারলোডেড অপারেটরকে কল করে bঅজেক্ট, তবে এটি System.Object.ReferenceEquals()প্রায় এক ডিগ্রিতে কাজ করে - কেবল মনে রাখবেন যে একটি ডিস্ট্রয় () এড গেমওজেক্ট ওভারলোডটি নাল হিসাবে সমান তুলনা করে, তবে এখনও শূন্যের জন্য রেফারেন্সএকুয়াল নয়।

    • ইউনিটির ধরণগুলি থেকে পরামিতিগুলি পড়া অন্য থ্রেডে সাধারণত নিরাপদ থাকে (যেহেতু আপনি উপরে যতটা নাল পরীক্ষা করতে যত্নবান হন ততক্ষণে অবিলম্বে কোনও ব্যতিক্রম ছুঁড়ে ফেলা হবে না) তবে এখানে ফিলিপের সতর্কতা নোট করুন যে মূল থ্রেডটি রাষ্ট্র পরিবর্তন করতে পারে যখন আপনি এটি পড়ছেন। কিছু অসঙ্গত অবস্থায় পড়া এড়ানোর জন্য কাকে কী পরিবর্তন করার অনুমতি দেওয়া হয়েছে সে সম্পর্কে আপনাকে শৃঙ্খলাবদ্ধ হতে হবে, যা আপনার ত্রিশের মধ্যে সাব-মিলিসেকেন্ড সময়ের উপর নির্ভরশীল এমন বাগগুলি সন্ধান করতে পারে যেগুলি ত্রুটিযুক্তভাবে অনুসরণ করা শক্ত হতে পারে they ইচ্ছায় পুনরুত্পাদন করা হবে না।

    • এলোমেলো এবং সময় স্থির সদস্যদের পাওয়া যায় না। সিস্টেমের উদাহরণ তৈরি করুন need থ্রেডের প্রতি র্যান্ডম যদি আপনার এলোমেলো প্রয়োজন হয়, এবং সিস্টেম.ডায়াগনস্টিক্স S স্টপওয়াচ আপনার সময়সীমার তথ্য প্রয়োজন হলে স্টপওয়াচ করুন।

    • ম্যাথফ ফাংশন, ভেক্টর, ম্যাট্রিক্স, কোয়ার্ট্রিয়েন এবং রঙ সমস্ত থ্রেড জুড়ে সূক্ষ্মভাবে কাজ করে, যাতে আপনি আপনার বেশিরভাগ গণনা আলাদাভাবে করতে পারেন you

    • গেমঅবজেক্টস তৈরি করা, মনোবিহাইওয়েরগুলি সংযুক্ত করা, বা টেক্সচার, মেশস, উপকরণ ইত্যাদি তৈরি / আপডেট করা ইত্যাদির মূল থ্রেডে ঘটতে হবে। অতীতে যখন এগুলির সাথে কাজ করার দরকার হয়েছিল তখন আমি একটি প্রযোজক-ভোক্তা সারি সেট আপ করেছি, যেখানে আমার কর্মী থ্রেড কাঁচা ডেটা প্রস্তুত করে (জাল বা টেক্সচারের জন্য প্রয়োগ করতে ভেক্টর / রঙের বড় অ্যারের মতো), এবং ডেটাগুলির জন্য মূল থ্রেড পোলে একটি আপডেট বা করোটিন এবং এটি প্রয়োগ করে।

এই নোটগুলি বাইরে না যাওয়ার সাথে সাথে এখানে একটি প্যাটার্ন দেওয়া হয়েছে যা আমি প্রায়শই থ্রেডেড কাজের জন্য ব্যবহার করি। আমি কোনও গ্যারান্টি দিচ্ছি না যে এটি একটি সেরা অনুশীলন শৈলী, তবে এটি কাজটি করে। (উন্নতি করার জন্য মন্তব্য বা সম্পাদনাগুলি স্বাগত - আমি জানি থ্রেডিং একটি খুব গভীর বিষয় যা আমি কেবলমাত্র বেসিকগুলি জানি)

using UnityEngine;
using System.Threading; 

public class MyThreadedBehaviour : MonoBehaviour
{

    bool _threadRunning;
    Thread _thread;

    void Start()
    {
        // Begin our heavy work on a new thread.
        _thread = new Thread(ThreadedWork);
        _thread.Start();
    }


    void ThreadedWork()
    {
        _threadRunning = true;
        bool workDone = false;

        // This pattern lets us interrupt the work at a safe point if neeeded.
        while(_threadRunning && !workDone)
        {
            // Do Work...
        }
        _threadRunning = false;
    }

    void OnDisable()
    {
        // If the thread is still running, we should shut it down,
        // otherwise it can prevent the game from exiting correctly.
        if(_threadRunning)
        {
            // This forces the while loop in the ThreadedWork function to abort.
            _threadRunning = false;

            // This waits until the thread exits,
            // ensuring any cleanup we do after this is safe. 
            _thread.Join();
        }

        // Thread is guaranteed no longer running. Do other cleanup tasks.
    }
}

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

using UnityEngine;
using System.Collections;

public class MyYieldingBehaviour : MonoBehaviour
{ 

    void Start()
    {
        // Begin our heavy work in a coroutine.
        StartCoroutine(YieldingWork());
    }    

    IEnumerator YieldingWork()
    {
        bool workDone = false;

        while(!workDone)
        {
            // Let the engine run for a frame.
            yield return null;

            // Do Work...
        }
    }
}

এটির জন্য কোনও বিশেষ পরিষ্কারের বিবেচনার প্রয়োজন নেই, যেহেতু ইঞ্জিনটি (যতদূর আমি বলতে পারি) আপনার জন্য ধ্বংসপ্রাপ্ত বস্তুগুলি থেকে কর্টিনগুলি থেকে মুক্তি পাবে।

পদ্ধতির সমস্ত স্থানীয় রাজ্য সংরক্ষণ করা হয় যখন এটি আসে এবং পুনরায় শুরু হয়, তাই অনেকগুলি উদ্দেশ্যে এটি অন্য থ্রেডে নিরবচ্ছিন্নভাবে চলমান ছিল (তবে আপনার কাছে মূল থ্রেডে চলার সমস্ত সুবিধা রয়েছে)। আপনার কেবল এটি নিশ্চিত করতে হবে যে এর প্রতিটি পুনরাবৃত্তি যথেষ্ট সংক্ষিপ্ত যে এটি আপনার মূল থ্রেডটি অযৌক্তিকভাবে ধীর করে দিচ্ছে না।

গুরুত্বপূর্ণ ক্রিয়াকলাপগুলি কোনও ফলন দ্বারা আলাদা করা হয় না তা নিশ্চিত করে আপনি একক থ্রেডযুক্ত আচরণের ধারাবাহিকতা পেতে পারেন - মূল থ্রেডের কোনও অন্য লিপি বা সিস্টেম আপনি কাজ করার মাঝখানে থাকা ডেটা পরিবর্তন করতে পারবেন না তা জেনে।

ফলন ফেরতের লাইন আপনাকে কয়েকটি বিকল্প দেয়। আপনি করতে পারেন ...

  • yield return null পরবর্তী ফ্রেমের আপডেটের পরে পুনরায় শুরু করতে ()
  • yield return new WaitForFixedUpdate() পরবর্তী স্থির আপডেটের পরে পুনরায় শুরু করতে ()
  • yield return new WaitForSeconds(delay) নির্দিষ্ট সময় গেম সময় ব্যয় করার পরে আবার শুরু করতে
  • yield return new WaitForEndOfFrame() জিইউআই রেন্ডারিং শেষ করার পরে আবার শুরু করতে
  • yield return myRequestযেখানে myRequestএকটি হল বা WWW উদাহরণস্বরূপ অনুরোধ করা তথ্য ওয়েব বা ডিস্ক থেকে লোড করা শেষ একবার পুনরায় শুরু করতে।
  • yield return otherCoroutineসম্পূর্ণ হওয়ার পরে আবার শুরু করার জন্য যেখানে otherCoroutineএকটি কর্টাইন উদাহরণ রয়েছেotherCoroutine । এটি প্রায়শই ফর্মটিতে yield return StartCoroutine(OtherCoroutineMethod())একটি নতুন কর্টিনে কার্যকর করার শৃঙ্খলা হিসাবে ব্যবহার করা হয় যা যখন এটি চায় তখন ফলন করতে পারে।

    • পরীক্ষামূলকভাবে, দ্বিতীয়টি এড়িয়ে যাওয়া StartCoroutineএবং yield return OtherCoroutineMethod()যদি আপনি একই প্রসঙ্গে বাস্তবায়নের শৃঙ্খলা করতে চান তবে কেবল লেখাই একই লক্ষ্য অর্জন করে।

      StartCoroutineযদি আপনি দ্বিতীয় বস্তুর মতো মিলিয়ে নেস্টেড কর্টিন চালাতে চান তবে কোনওটির অভ্যন্তরে মোড়ানো এখনও কার্যকর হতে পারেyield return otherObject.StartCoroutine(OtherObjectsCoroutineMethod())

... আপনি যখন কর্টিনটি এর পরবর্তী বারটি নেবেন তখন তার উপর নির্ভরশীল।

বা yield break;কর্টিন শেষ হওয়ার আগে থামাতে, আপনি যেভাবে return;কোনও প্রচলিত পদ্ধতিটি প্রারম্ভিক-আউট ব্যবহার করতে পারেন ।


পুনরাবৃত্তির পরিমাণ 20 মিমি বেশি গ্রহণের পরেই কি কর্টিনগুলি উত্পন্ন করার কোনও উপায় আছে?
ডার্কডেস্ট্রি

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

1
ভাল উত্তর! আমি কেবল যুক্ত করতে চাই যে কর্টিনগুলি ব্যবহার করার আরও একটি কারণ হ'ল যদি আপনার যদি কখনও ওয়েবগেল তৈরির প্রয়োজন হয় যা এটি কাজ করবে যা আপনি থ্রেড ব্যবহার করেন না তবে এটি কাজ করবে না। এখনই একটি বিশাল প্রকল্পে সেই মাথা ব্যাথা নিয়ে বসে আছেন: পি
মিকেল হগ্রস্ট্রমে

ভাল উত্তর এবং ধন্যবাদ। শুধু ভাবছি কী যদি আমাকে থ্রেডটি একাধিকবার থামাতে এবং পুনরায় চালু করতে হবে, তবে আমি
গর্ভবতী

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

0

আপনি আপনার ভারী গণনাটিকে অন্য থ্রেডে রাখতে পারেন, তবে ইউনিটির API এ থ্রেড নিরাপদ নয়, আপনাকে সেগুলি মূল থ্রেডে চালিত করতে হবে।

ভাল আপনি এই প্যাকেজটি সম্পদ স্টোরটিতে চেষ্টা করতে পারেন থ্রেডিং সহজতর করতে আপনাকে সহায়তা করবে। http://u3d.as/wQg আপনি কেবল একটি থ্রেড শুরু করতে এবং ইউনিটি এপিআই নিরাপদে কার্যকর করতে কোডের একটি লাইনই ব্যবহার করতে পারেন।



0

@ ডিএমজি গ্রেগরি এটি সত্যই ব্যাখ্যা করেছে explained

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

ইউনিটি উইকিতে সত্যিই ভাল জবকিউ উদাহরণ স্ক্রিপ্ট রয়েছে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.