Edited at

UnityThreadQueueというUnityのライブラリを作成しました。

UnityThreadQueueという、Unity上でThreadを使って、非同期処理をQueueを使って行うためのライブラリを公開しました。

https://github.com/TakuKobayashi/UnityThreadQueue

よかったら使っていただけたらと思います。m(_ _)m。starももらえるとうれしいです。

以下、使い方と作成経緯とThreadとかQueueとかUnityにおける仕様とかの前提知識について書きます。


使い方

UnityThreadQueue.unitypackageがあるので、それをインストールしてください。

AsyncSample.cs(非同期でやるもの)とSyncSample.cs(同期するもの)でサンプルを作成しましたのでそれも参照してください。


  • 基本的な使い方


AsyncSample.cs

UnityThreadQueue.Instance.Enqueue (() => {

//非同期で行いたい処理を記述
});


  • 非同期(Thread)で実行中の処理があるかどうか


SyncSample.cs

public bool UnityThreadQueue.Instance.ExistQueueEvent;



  • 上記二つを組み合わせて、Threadで行われた処理と同期させる一例


SyncSample.cs

void Start(){

UnityThreadQueue.Instance.Enqueue (() => {
//非同期で行いたい処理を記述
});
StartCoroutine (SyncCorutine());
}

private IEnumerator SyncCorutine(){
while (UnityThreadQueue.Instance.ExistQueueEvent) {
yield return null;
}
// 同期させた後に書きたい処理を書く
}



処理概要

上記タイミング図のようにEnqueueすると別スレッドで処理が行われます。

(今回行われる処理では処理が完了するまでに100の時間がかかるものとします)

基本的にMainThreadの他に一つだけ別スレッドが立ち、その別スレッド内で処理が行われます。(スレッドとして立っているものは合計2個だけになります)

別スレッドの処理が終わる前にEnqueueした場合、すでに入っている処理が終わり次第、新しく入った処理がそのスレッド内で行われます。(タイミング図参照)

Queueの中に入っている処理が全てなくなったら、アイドル状態となります。

(なお上記のタイミング図はPlantUMLを使って表示しています。以下に記述内容を記載します。)

@startuml

robust "QueueThread" as QT
concise "MainThread" as MT

@0
MT is 処理中
QT is アイドル

@+100
MT -> QT : Enqueue
MT is 処理中
QT is 処理中

@+100
QT -> MT : 終了通知
MT is 処理中
QT is アイドル

@+100
MT -> QT : Enqueue
MT is 処理中
QT is 処理中

@+50
MT -> QT : Enqueue
MT is 処理中
QT is 処理中

@+150
QT -> MT : 終了通知
MT is 処理中
QT is アイドル

@enduml


経緯

時間がかかる処理を高速かつ、制御できるものが必要になったためです。

(※制御できるもの: 非同期処理を行うThreadが乱立することなく、処理が行われる順番も担保されているもの)

また、使うにあたり、あらゆるところから呼び出せるようにもしました。


概要

Unityは基本的に非同期の処理をコルーチンで処理するが、コルーチンは基本的に同期処理(非同期のように見せているだけ)なので、時間がかかる処理の場合には画面が固まってしまったり、Totalの処理時間は変わらないため、結局時間がかるなど、注意が必要。(詳しくは後述)

そのため、この問題の解決にもこのライブラリは有用です。


前提知識


Queue(キュー)

Queueとはコンピュータの基本的なデータ構造の一つ。以下の図のようにデータを先入れ先出しのリスト構造で保持するもの。



今回、実装したものは処理を入れた(Enqueueした)順番で実行していく仕組み。


並行処理(マルチタスク)

コンピュータにおいて複数のタスクを切り替えて実行できるシステムのこと。

一般的にCPUを効率的に使用することで並行処理を実現している。CPUの利用単位として一般的にスレッドとプロセスがあり、それらを用いてマルチタスクを実現させるのが一般的。

なお、基本的に並行処理を実装する場合、制御する難度が格段に上がるので注意が必要


Process(プロセス)

プロセスはCPU上で実行されるもので、タスクを完了するために、OSが制御するあらゆるリソースを使うことができます。

一般的にアプリ起動 → プロセス起動


Thread(スレッド)

スレッドとは、CPU利用の単位を指します。スレッドは1つのプロセスから生成される実行単位で、同じプロセスから1つ以上のスレッドを起動させて実行させることができます。


コルーチン

コルーチンとはプログラミングの構造の一種。サブルーチンがエントリーからリターンまでを一つの処理単位とするのに対し、コルーチンはいったん処理を中断した後、続きから処理を再開できる。(このような機能を持った処理)

Unityにおける、コルーチンは処理が行われる順番が、フレーム単位で分けて実行されているだけであって、実際にはマルチタスクが行われているわけではないので厳密には非同期処理ではない。


UnityにおけるThreadを使った非同期処理について

上記、非同期で行いたい処理はの中では、Unityの提供しているAPI(using UnityEngineが必要なもの)は使用できない。(使用するとエラーになる)

これはUnityの仕様で、非同期処理中はThreadで処理が行われているためです。


参考

Unityでスレッドを使う

Unityの非同期処理



2017/11/28更新

ライブラリのプロジェクトを移動させることにしました。

新しいものはこちらになります。

https://github.com/TakuKobayashi/UnityThreadQueue

以前のものはアーカイブにしました。