このブログはUnityの初心者向けに、Untiyの機能の使い方、基本のスクリプトファイルの使い方から応用までをご説明しています。中級以上の方に読んでいただきたい内容も随時更新していますので、お時間がある方、検索でここにアクセスされた方はぜひ立ち寄っていってください。
前回の記事では Update関数の中で、フレーム間の時間を返す「Time.deltatime」を累積して、指定の時間を超えたときにイベントが発動するという方法で、連続で弾を発射し続ける方法動きを作成しました。 今回は「Coroutine(コルーチン)」を使用して、同じ動きを実現する方法のご説明です。
下の動画は「ファイブボックス 一分間Unity講座 定期的に弾を撃ち続ける方法2」 のショート動画です。ご興味がございましたら、こちらの動画もご参照ください。
1 素材作成と配置
事前に前回の記事をご参照頂き、ステージ上にPlayerを配置、さらにPlayerから発射されるBullett を作成し、プレハブ化の準備をしておきます。
Playerには発射用のスクリプトファイル「PlayerShot」を作成、アタッチし、以下のコード(前回のものを流用)を記述します。
[SerializeField] GameObject bulletPrefab; //Bulletのプレハブ
void Update()
{
//前回の記事で作成したコードは削除、またはコメントアウト
}
2 コルーチンの作成
関数内で待機時間を設けるには、コルーチンを活用します。
コルーチン関数は「IEnumerator型」を指定し、yield return を使って後続処理に移行するまでの時間を返します。
IEnumerator ShotCoroutine()
{
while (true) //無限ループ
{
yield return new WaitForSeconds(0.2f); //0.2秒待機
//Playeの場所に弾を生成し bullet という名前で変数化
GameObject bullet =
Instantiate(bulletPrefab, transform.position, Quaternion.identity);
//bulletからRigidbodyコンポーネントを取得し、上向きの力を加える
bullet.GetComponent<Rigidbody2D>().AddForce(transform.up *200);
Destroy(bullet, 2.0f); //bullet を2秒後に削除
}
}
このコードでは while(true){ } を指定して、無限ループを作っています。Start関数で1度だけ呼び出します。Update関数内で使ってしまうと、処理が暴走しフリーズしてしまうので気を付けましょう。
コルーチンを呼び出す際には「StartCoroutine()」メソッドを使用、引数に対象のコルーチンを指定します。
void Start()
{
StartCoroutine(ShotCoroutine()); //ShotCoroutineを呼び出す
}
前回と同じですが、PlayerにアタッチしたPlayerShot、[SerializeField]で宣言した bulletPrefab にBulletのプレハブをAssignし、プロジェクトを起動させてみましょう。
0.2秒に1発ずつ、上方に弾を発射しているのが確認できたと思います。
3 コルーチンの待ち時間
上の事例では yield return new WaitForSeconds(0.2f) を使って 0.2秒待機しました。
待ち時間の指定は、他にも以下のようなものがあります。
1. yield return null
効果:次のフレームまで待機する
次のフレームが開始されるまで一時停止します。フレーム単位での処理を分割する際に便利です。
IEnumerator WaitForNextFrame()
{
Debug.Log("開始フレーム: " + Time.frameCount);
yield return null;
Debug.Log("次のフレーム: " + Time.frameCount);
}
2. yield return new WaitForSeconds(float seconds)
効果: 指定した秒数待機する 指定された時間が経過するまでコルーチンを中断します。リアルタイムスケールに基づきます。例えば、Time.timeScale を0.5に設定すると、ゲーム内の時間が通常の半分の速度で流れるため、WaitForSeconds(1.0f)は実際には2秒かかります。
IEnumerator WaitForSecondsTime()
{
Debug.Log("開始時間: " + Time.time);
yield return new WaitForSeconds(2.0f);
Debug.Log("2秒後: " + Time.time);
}
3. yield return new WaitForSecondsRealtime(float seconds)
効果: 指定した秒数リアルタイムで待機する
Time.timeScaleの影響を受けず、リアルタイムでの待機が行われます。
IEnumerator WaitForSecondsRealtime()
{
Debug.Log("開始時間: " + Time.realtimeSinceStartup);
yield return new WaitForSecondsRealtime(2.0f);
Debug.Log("2秒後: " + Time.realtimeSinceStartup);
}
4. yield return new WaitUntil(Func<bool> predicate)
効果: 条件が満たされるまで待機する
指定された条件 (predicate) がtrueになるまで待機します。
IEnumerator WaitUntilBool()
{
Debug.Log("スペースキーが押されるまでお待ちください");
yield return new WaitUntil(() => Input.GetKeyDown(KeyCode.Space));
Debug.Log("スペースキーが押された!");
}
5. yield return new WaitWhile(Func<bool> predicate)
効果: 条件が満たされている間待機する
指定された条件 (predicate) がtrueである間、待機します。
IEnumerator WaitWhileBool()
{
//スペースキーが押された状態でコルーチンを発動
Debug.Log("スペースキーが離されるまでお待ちください");
yield return new WaitWhile(() => Input.GetKey(KeyCode.Space));
Debug.Log("スペースキーが離された");
}
6. yield return StartCoroutine(IEnumerator routine)
効果: 他のコルーチンが終了するまで待機する
指定した別のコルーチンが終了するのを待機します。下の事例では、ThisCoroutine()を呼び出すと、OtherCoroutine()が呼び出され、終了したタイミングで後続処理に移動します。別途 OtherCoroutine() を呼び出す必要はありません。
IEnumerator ThisCoroutine()
{
yield return StartCoroutine(OtherCoroutine());
Debug.Log("OtherCoroutine が終了した");
}
IEnumerator OtherCoroutine()
{
yield return new WaitForSeconds(3.0f);
Debug.Log("OtherCoroutine起動中、終了までお待ちください");
}
7. yield break
効果: コルーチンを即座に終了する
リソースを節約するために早めにコルーチンを止めます。または予期しない状況で安全に終了するために使用します。 下の事例では、PlayerのHPに応じてコルーチンを継続するか即中断するかを指定しています。引数で受け取った playerHP が0の場合、yield bleak でコルーチンを即座に終了します。
IEnumerator HPYieldBreak(int playerHP)
{
Debug.Log("バトルスタート");
yield return new WaitForSeconds(1.0f);
// 条件をチェックして、コルーチンを終了
if (playerHP <= 0)
{
Debug.Log("先頭不能、コルーチンを終了");
yield break; // コルーチンを終了
}
Debug.Log("Playerはまだ生きている");
yield return new WaitForSeconds(1.0f); // 1秒待機
Debug.Log("バトル継続");
}
使用するタイミングや要件によって、上の事例を参考にご利用ください。
ファイブボックスでは、スクラッチやUnityの個別指導のオンラインレッスンを行っています。
Kommentare