序
基本的に扱い方は分ってるという前提ですので、ご了承ください。
実際に使ってみて分った事なので、
既にガッツリ使われている人には、あまりメリットがないかもしれません。
ご参考までにという事で。
コルーチンの止め方
StopCoroutine(~~) で止める訳だが、引数には3つ取る事が出来る。
- String型
- IEnumerator型
- Coroutine型
大体の場合に置いて、String型がいいよ、という事になっているわけだが、
それは、メソッド名で動かした時に、止めるときに同じ方法で止まらないからだ。
だが、Stringで渡した時に致命的な欠点があって、
MonoDevelop上から、F2で置き換えた場合に、Stringなので当然一緒に置き変わらないというところだ。
これはコンパイルチェック上から外れてしまうので当然なわけだ。
(そんな迂闊なことしない? まあその通りだが。)
単純にStringが気持ち悪く、
恐らく Coroutine型 で止めるのが一番気持ちいいと思うのだが、
意外と情報がないので記載する事にした。
using UnityEngine;
using System.Collections;
public class coroutinStopTest : MonoBehaviour {
	void Start () {
		Coroutine retC = StartCoroutine (mainLoop());
		StopCoroutine (retC);
	}
	IEnumerator mainLoop(){
		while (true) {
			Debug.Log ("loop Coroutine");
			yield return new WaitForSeconds (0.5f);
		}
	}
}
StartCoroutine の戻り値が Coroutine型なので、
それを引数に StopCoroutine すれば良い。
これもんの、
	Coroutine retC = StartCoroutine (mainLoop());
これということ。
	StopCoroutine (retC);
サンプルソースの場合は、直ぐに停止されるので、ログは出ない。
ちゃんと動いて止まった事を確認したい人は、下の方のソースを見てください。
これがいちばんスマートで直感的だと思うのだが、
検索すると IEnumerator で止める方法が一番最初に上がってくるから不思議だ。
コルーチンの実行タイミングと時間間隔
これは実際に使った人は大体分っているものと思う。
・実行タイミング
これは、描写間隔と同期される。
つまり、WaitTimeを極小にした場合、Update() と同じタイミングで実行される。
・ yield return new WaitForSeconds (0.00001f);
などとしても、毎フレームに抑えられる。
・時間間隔の計測タイミング
上記のような極小タイミングだった場合、1フレームに沢山実行されない事から分るように、
「フレーム毎に、規定時間を過ぎていた場合に実行する」という処理であるといえる。
Time.timescale を少し小さくしてみると、その処理誤差が段々顕著になる。
WaitForSeconds は当然 Time.timescale の影響を受けるが、
毎フレームのタイミングを遅らせるものではない為、
規定時間を経過したと判定され、毎フレーム実行される。
止めるコルーチンに、retC を引数で渡している。
using UnityEngine;
using System.Collections;
public class coroutinStopTest2 : MonoBehaviour {
	void Start () {
		Time.timeScale = 0.1f;
		Coroutine retC = StartCoroutine (mainLoop());
		StartCoroutine (stopWait(retC));
	}
	IEnumerator mainLoop(){
		yield return new WaitForSeconds (0.2f); //実行時処理の遅延の解消のため
		while (true) {
			yield return new WaitForSeconds (0.0001f);
			Debug.Log ("time : " + Time.deltaTime);
		}
	}
	IEnumerator stopWait(Coroutine retC){
		yield return new WaitForSeconds (2f);
		StopCoroutine (retC);
		Debug.Log ("stop Coroutine");
	}
}
つまり、極小の待機時間にした場合、殆どUpdate()と同じ動きになるという事だ。
で、何が言いたいかというと
Update() と同じ働きに近いが、Time.timescale の影響を受ける。
これを逆に利用して、ポーズ処理の実装が面倒な雑なアプリを作る時には、
Time.timescale = 0 で使えるのではないかという話。
とは言え、ポーズ処理はコンポーネントを無効化するのが一番無難そうですよね。
個人的には、パーティクルシステムが Time.timescale = 0 で動く方法があれば、
大体ビジュアル的にも問題ないですし、これでオッケーなんじゃないかと思ったりするわけですがw
ちなみに、yield return null とした場合は、
時間関数を通らないので、Time.timescale = 0 の影響は受けませんので、
そこは誤解の無きよう。
あと、今回の内容を踏まえてもらうと分ると思うのですが、
通常の使い方でも、WaitForSecondsでループする時は、
それなりに大きい待ち時間じゃないと時間誤差が大きく出るので、あまりよくないです(と思います)。
手抜き上等な方は、こっそり使ってみてはどうでしょうか
(全く推奨しませんがw)