#序
基本的に扱い方は分ってるという前提ですので、ご了承ください。
実際に使ってみて分った事なので、
既にガッツリ使われている人には、あまりメリットがないかもしれません。
ご参考までにという事で。
#コルーチンの止め方
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)