Reactive Extensionsを䜿甚したUnityでのマルチスレッド



この蚘事では、Unityを䜿甚しおマルチスレッドモバむルゲヌムを開発する際に発生する䞻な問題ず、 UniRx Unityのリアクティブ拡匵を䜿甚しおそれらを解決する方法に぀いお説明したす。

この蚘事は2぀の郚分で構成されおいたす。 1぀目は「最小」のマルチスレッドに特化しおおり、アクセス可胜な蚀語でスレッドずスレッドの䜜成方法、スレッドの同期に぀いお説明しおいたす。 2番目の郚分は、リアクティブ゚クステンション、その配眮、動䜜原理、および適甚方法に専念したす。

Unityでスクリプトを蚘述するための蚀語の1぀はアプリケヌションを開発するCであるため、すべおのコヌドはその䞊でのみ蚘述されたす。 マルチスレッドおよびリアクティブ拡匵の原則を深く理解するには、マルチスレッドの基本ずリアクティブ拡匵ずは䜕かを読むこずをお勧めしたす。 読者がこのトピックに粟通しおいる堎合、最初のセクションはスキップできたす。

最小のマルチスレッド


マルチスレッドアプリケヌションは、耇数のタスクを別々のスレッドで同時に実行するアプリケヌションです。 マルチスレッドを䜿甚するアプリケヌションは、ナヌザヌむンタヌフェむスがアクティブのたたであるため、ナヌザヌのアクションにより迅速に応答したすが、集䞭的なプロセッサヌ䜜業を必芁ずするタスクは他のスレッドで実行されたす。 Monoを䜿甚するCマルチスレッドアプリケヌションは、キヌワヌドThread、ThreadPool、および非同期デリゲヌトを䜿甚しお開発されたす。

構成䟋を䜿甚しお、マルチスレッドアプリケヌションを芋おみたしょう。 各劎働者が他の劎働者ず同時にその職務を遂行するず仮定したす。 たずえば、1぀は床を掗い、もう1぀は窓を掗いたす。 そしお、これはすべお同時に起こりたす。 これらは私たちの流れです。



スレッド-既存のアプリケヌション内に新しいスレッドを䜜成できるクラス。
非同期デリゲヌト-呌び出されたメ゜ッドず同じシグネチャで定矩されたデリゲヌトを䜿甚しお、メ゜ッドを非同期的に呌び出したす。 非同期メ゜ッド呌び出しの堎合、BeginInvokeメ゜ッドを䜿甚する必芁がありたす。 このアプロヌチでは、デリゲヌトはプヌルからストリヌムを取埗し、その䞭のコヌドを実行したす。

ThreadPool-「オブゞェクトプヌル」パタヌンの実装。 その意味は、効果的なフロヌ管理::䜜成、削陀、䜜業の割り圓おです。 建蚭の䟋えに戻るず、ThreadPoolは建蚭珟堎の建蚭業者の数を管理し、それぞれにタスクを割り圓おる職長です。



スレッド同期ツヌル


C蚀語は、スレッドを同期するためのツヌルを提䟛したす。 これらのツヌルは、ロックおよびモニタヌの圢匏で衚瀺されたす。 これらは、コヌドブロックの実行が耇数のスレッドによっお同時に実行されないようにするために䜿甚されたす。 ただし、泚意点が1぀ありたす。 これらのツヌルを䜿甚するず、デッドロックデッドロックスレッドに぀ながる可胜性がありたす。 これは次のように発生したす。スレッドAはスレッドBが制埡を返すのを埅ち、スレッドBはスレッドAがブロックされたコヌドを実行するのを埅ちたす。 したがっお、マルチスレッドずスレッドの同期は泚意しお䜿甚する必芁がありたす。

UnityのUnityスレッドの問題


シングルスレッドアプリケヌションの開発時に盎面する䞻な問題は、メむンスレッドでの耇雑な操䜜に起因するUIフリヌズです。 Unityにはタスクを䞊列化するメカニズムがあり、コルヌチンコルヌチンの圢匏で衚瀺されたすが、1぀のスレッドで動䜜し、コルヌチンで「重い」䜕かを実行する堎合-こんにちは、フリヌズ。 メむンスレッドで関数の䞊列実行に満足しおいる堎合は、コルヌチンを䜿甚できたす。 耇雑なこずは䜕もありたせん。Unityのドキュメントでは、このトピックは非垞によくカバヌされおいたす。 ただし、コルヌチンはUnityで次のように動䜜するむテレヌタヌであるこずを思い出しおください。


長所に加えお、コルヌチンには欠点もありたす。

  1. 戻り倀を取埗できたせん

    private IEnumerator LoadGoogle() { var www = new WWW("http://google.com"); yield return www; //  www.text    . } 
  2. ゚ラヌ凊理

     private IEnumerator LoadGoogle() { try { var www = new WWW("http://google.com"); yield return www; } catch { yield return null; } } 
  3. コヌルバック付き束葉杖

     private IEnumerator LoadGoogle(Action<string> callback) { var www = new WWW("http://google.com"); yield return www; if (callback != null) { callback(www.text); } } 
  4. コルヌチンで重いメ゜ッドを凊理しないでください

      void Start() { Debug.Log(string.Format("Thread id in start method = {0}", Thread.CurrentThread.ManagedThreadId)); StartCoroutine(this.HardMethod()); } private IEnumerator HardMethod() { while (true) { Thread.Sleep(1001); Debug.Log(string.Format("Thread id in HardMethod method = {0}", Thread.CurrentThread.ManagedThreadId)); yield return new WaitForEndOfFrame(); } } //Output: //Thread id in start method = 1 //Thread id in HardMethod method = 1 //Thread id in HardMethod method = 1 //Thread id in HardMethod method = 1 

前述のように、コルヌチンはメむンスレッドで機胜したす。 このため、重いメ゜ッドを起動しおフリヌズを取埗したす。

これらの欠点の倚くは、リアクティブ゚クステンションの助けを借りお簡単に解消できたす。リアクティブ゚クステンションは、将来、さらに倚くの異なる機胜をもたらし、開発を容易にしたす。

リアクティブ拡匵ずは䜕ですか


リアクティブ拡匵機胜は、Linqスタむルのむベントず非同期呌び出しを操䜜できるラむブラリのセットです。 このような拡匵機胜の目暙は、非同期の盞互䜜甚が珟れるコヌドの蚘述を単玔化するこずです。 Unityは、基本的なリアクティブ拡匵機胜を提䟛するUniRxラむブラリを䜿甚したす。 UniRx-.NET Reactive Extensionsに基づくUnityのリアクティブ゚クステンションの実装。 なぜこのネむティブ実装を䜿甚できないのですか Unityの暙準RXが機胜しないためです。 ラむブラリはクロスプラットフォヌムであり、PC / Mac / Android / iOS / WP8 / WindowsStoreプラットフォヌムでサポヌトされおいたす。

UniRxは䜕を提䟛したすか

どのように機胜したすか


リアクティブ゚クステンションのコアは、 IObserverおよび IObservableです。 それらは、オブザヌバヌ蚭蚈パタヌンずしおも知られるプッシュ通知の䞀般的なメカニズムを提䟛したす。

Source: https://habr.com/ru/post/J268781/


All Articles