テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

Unity非同期処理デザインについて

Unityの非同期処理について素晴らしい資料があったのでメモ

ここで紹介しているのはコルーチンを用いた非同期処理の方法。

Unityは基本的に1スレッドで動作する。なので時間がかかる処理を1フレームに突っ込むと、そのフレームが停止してしまう。ロードや大規模に停止しても問題ない処理ならばともかくリアルタイムで動く処理でフレーム停止を頻発されては問題。なので、時間のかかる処理を分散定義して、1フレームに極端に負荷をかけないように実行してやる形を取る事にするといった感じらしい。

要するに、計算に合計10秒かかる処理を「ゲームを10秒停止」させずに「0.2秒x50で行う」といった話。前者は画面がガッツリ止まるけど、後者は進捗表示とかアニメーションが表示できる。

スライドには応用として「Task」の使い方もあったが、こっちは良くわからないのでそのうち。多分これが自分のやりたい事と合致してるんだけど、ぐぬぬ

なおコルーチンは非同期ではなく遅延実行。本来は非同期処理(スレッド等)での処理を待ち受けるものです。

■コルーチンを用いた非同期処理
要するに、こんな感じで使うらしい
メソッド定義

IIEnumerator method()
{
  // 1フレーム目の処理
  yield return null;
  // 2フレーム目の処理
  yield return null;
}

呼び出し

void Function()
{
  StartCoroutine(method());
}

戻り値がIIEnumerator固定なので、戻り値が欲しいならメンバ変数とかに渡してやるか、コールバックを用意して読んでもらう形になるらしい。

ちなみにyield return WaitForSeconds(秒)で、次のフレームと言わず指定秒止めることができる。処理を「一定時間停止後にに再開」みたいな事ををしたい場合は非常に有用だと思う。例えばアニメーション完了後に処理を再開とか。

void Start()
{
   StartCoroutine(AnimationPlay("anim"));
}
IEnumerator AnimationPlay (string animationName) {
   animation.Play(animationName);
   yield return new WaitForSeconds(animation[animationName].length);
   Debug.Log("finished");
}

Startの戻り値をIEnumeratorにするとコルーチンとして呼ばれるらしいので、上の処理は下のようにも書くことができる。

IEnumerator Start()
{
   string animationName = "anim";
   float animationTime = animation[animationName].length;
   animation.Play(animationName);
   yield return new WaitForSeconds(animationTime);
   Debug.Log("finished");
}



実はコルーチン以外にもSpicy PixelやUnityThreadHelperといった非同期処理をサポートするアセットを使用する方法もあったりするのだが、その話はそのうち。

UnityThreadHelper
http://u3d.as/content/marrrk/unity-thread-helper/38a

Spicy Pixel Concurrency Kit
http://u3d.as/content/spicy-pixel/spicy-pixel-concurrency-kit/312