関数を呼び出すと、値を返す前に実行が完了します。これは、関数で行なわれるすべてのアクションは 1 つのフレーム内で行われるということを意味します。つまり、関数呼び出しにプロシージャルアニメーションを含んだり、時間経過が必要なイベントに使用することはできません。例として、オブジェクトのアルファ (透明度) を完全に見えなくなるまでなるまで徐々に減少させるタスクを考えてみましょう。
void Fade()
{
for (float ft = 1f; ft >= 0; ft -= 0.1f)
{
Color c = renderer.material.color;
c.a = ft;
renderer.material.color = c;
}
}
上記のままでは、Fade 関数に期待通りの効果を得られません。フェードが視覚的に分かるようにするためには、アルファが連続したフレームに渡って減少し、中間的な値がレンダリングされることが必要です。しかし、関数は 1 つのフレーム内で完全に実行され完了します。中間値は決して表示されず、オブジェクトは即時に透明になります。
このような状況を Update 関数にコードを追加して、フレームごとにフェードするように処理することも可能です。しかし、通常、このようなタスクではコルーチンを使用するとより便利です。
コルーチンとは、実行を停止して Unity へ制御を戻し、その次のフレームで停止したところから続行することができる関数です。C# では、コルーチンを以下のように宣言します。
IEnumerator Fade()
{
for (float ft = 1f; ft >= 0; ft -= 0.1f)
{
Color c = renderer.material.color;
c.a = ft;
renderer.material.color = c;
yield return null;
}
}
本質的にこれは、IEnumerator が戻り値の型で、yield return ステートメントを内部に持つことを宣言した関数です。yield return の行が実行を停止して次のフレームから実行を継続する位置です。コルーチンを実行するには StartCoroutine 関数を使用します。
void Update()
{
if (Input.GetKeyDown("f"))
{
StartCoroutine("Fade");
}
}
Fade 関数のループカウンターは、コルーチンの生存期間を通して正しい値を保持します。実際、yield が発生しても、変数やパラメーターは正しく保持されます。
デフォルトでは、コルーチンは yield した直後のフレームで再開しますが、WaitForSeconds 関数を使用して、時間的に遅延させて再開することもできます。
IEnumerator Fade()
{
for (float ft = 1f; ft >= 0; ft -= 0.1f)
{
Color c = renderer.material.color;
c.a = ft;
renderer.material.color = c;
yield return new WaitForSeconds(.1f);
}
}
この方法はエフェクトを一定の時間遅延させるために使用できますが、最適化の方法としても便利です。ゲーム中のタスクの多くは定期的に行なう必要があります。もっとも分かりやすい方法としては Update 関数にそれらを加えてしまうことです。ただし、この関数は、通常 1 秒間に何度も呼び出されます。タスクがそれほど頻繁に繰り返す必要がない場合は、コルーチンに入れることで毎フレーム実行することなく定期的に更新することができます。例えば、敵が近くにいることをプレイヤーに知らせるアラームなどは良い例です。コード例は以下の通りです。
function ProximityCheck()
{
for (int i = 0; i < enemies.Length; i++)
{
if (Vector3.Distance(transform.position, enemies[i].transform.position) < dangerDistance) {
return true;
}
}
return false;
}
敵が数多く存在する場合は、この関数を毎フレーム呼び出しすると著しいオーバーヘッドが生じるかもしれません。しかし、コルーチンを使用して 1/10 秒ごとに呼び出すことができます。
IEnumerator DoCheck()
{
for(;;)
{
ProximityCheck();
yield return new WaitForSeconds(.1f);
}
}
このようにすると、ゲームにオーバーヘッドを与えずにチェック回数を大幅に削減できます。
ノート: StopCoroutine と StopAllCoroutines でコルーチンを停止できます。
コルーチンは、アタッチされているゲームオブジェクトが SetActive(false) で無効にされたときにも停止します。Destroy(example)
(example
は MonoBehaviour インスタンス) は即座に OnDisable
をトリガーし、コルーチンが処理され、効果的にそれを停止します。最後に OnDestroy
がフレームの最後に呼び出されます。
MonoBehaviour インスタンスで enabled を false に設定して MonoBehaviour を無効にしても、コルーチンは 停止しません。
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.