質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

937閲覧

Unityで◯秒後処理するようにしたい

mochinotane

総合スコア13

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2019/07/22 06:59

編集2019/07/22 07:06

前提・実現したいこと

Unityで2Dシューティングゲームを作っています。
こちらのチュートリアルを改造しており、グラフィック以外はほぼ同様のシューティングゲームです。

元のスクリプトでは、StartCoroutine("DelayTitle");の箇所にそのまま
GameOverメソッドを呼び出す処理が入っており、その状態だと衝突直後にタイトル表示に移ってしまいます。

プレイヤーがやられた図を見せたいので、衝突→2秒後にタイトル画面へ遷移するようにしたいです。

発生している問題・エラーメッセージ

こちらを参考に、コルーチンを利用して実装しようとしたのですが、
yield return new WaitForSeconds(2.0f);
↑この1行から先がうまく処理されず、タイトル画面へ遷移ができません。
(コルーチン宣言内の前後のDebug.logにて確認しています)

GameOverメソッドはManager.cs内にあり、ぶつかると呼び出すようになっています。

該当のソースコード

Player.cs

C#

1using UnityEngine; 2using System.Collections; 3 4namespace CompletedAssets 5{ 6 public class Player : MonoBehaviour 7 { 8 9 //割愛 10 11 // ぶつかった瞬間に呼び出される 12 void OnTriggerEnter2D (Collider2D c) 13 { 14 // レイヤー名を取得 15 string layerName = LayerMask.LayerToName (c.gameObject.layer); 16 17 // レイヤー名がBullet (Enemy)の時は弾を削除 18 if (layerName == "Bullet (Enemy)") { 19 // 弾の削除 20 Destroy (c.gameObject); 21 } 22 23 // レイヤー名がBullet (Enemy)またはEnemyの場合は爆発 24 if (layerName == "Bullet (Enemy)" || layerName == "Enemy") { 25 26                   // 3秒後にタイトル表示 27 StartCoroutine("DelayTitle"); 28 29 // 爆発する 30 spaceship.Explosion (); 31 32 // Explosionを削除 33 Destroy (gameObject); 34 35 36 37 } 38 } 39 40 IEnumerator DelayTitle() 41 { 42        // crushはconsoleに表示あり 43 Debug.Log("crush"); 44 yield return new WaitForSeconds(2.0f); 45        // 2secondsはconsoleに表示されない 46 Debug.Log("2seconds"); 47 48 // Managerコンポーネントをシーン内から探して取得し、GameOverメソッドを呼び出す 49 FindObjectOfType<Manager> ().GameOver (); 50 } 51 } 52}

Manager.cs

C#

1using UnityEngine; 2 3namespace CompletedAssets 4{ 5 public class Manager : MonoBehaviour 6 { 7 // Playerプレハブ 8 public GameObject player; 9 10 // タイトル 11 private GameObject title; 12 13 14 void Start () 15 { 16 // Titleゲームオブジェクトを検索し取得する 17 title = GameObject.Find ("Title"); 18 } 19 20 void Update () 21 { 22 // ゲーム中ではなく、Xキーが押されたらtrueを返す。 23 if (IsPlaying () == false && Input.GetKeyDown (KeyCode.X)) { 24 GameStart (); 25 } 26 } 27 28 void GameStart () 29 { 30 // ゲームスタート時に、タイトルを非表示にしてプレイヤーを作成する 31 title.SetActive (false); 32 Instantiate (player, player.transform.position, player.transform.rotation); 33 } 34 35 public void GameOver () 36 { 37 FindObjectOfType<Score> ().Save (); 38 39 // ゲームオーバー時に、タイトルを表示する 40 title.SetActive (true); 41 } 42 43 44 45 public bool IsPlaying () 46 { 47 // ゲーム中かどうかはタイトルの表示/非表示で判断する 48 return title.activeSelf == false; 49 } 50 } 51}

試したこと

Invokeやカウントアップも試してみたのですがやり方が悪いのか呼び出されなかったりで解決できませんでした。

補足情報(FW/ツールのバージョンなど)

Unity Version 2017.4.29f1 Personal

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

コルーチンの呼び出し元のゲームオブジェクトが破棄されると、コルーチンも全て破棄されます。
ゲームオブジェクトをすぐ破棄せずに非表示にしておくか、コルーチンの呼び出し元を他のゲームオブジェクトにしてみてください。


追記:
(以下は動作未確認なので、上手くいかなかったら適宜修正してください)

Player.cs

C#

1using UnityEngine; 2using System.Collections; 3 4namespace CompletedAssets 5{ 6 public class Player : MonoBehaviour 7 { 8 9 //割愛 10 11 // ぶつかった瞬間に呼び出される 12 void OnTriggerEnter2D (Collider2D c) 13 { 14 // レイヤー名を取得 15 string layerName = LayerMask.LayerToName (c.gameObject.layer); 16 17 // レイヤー名がBullet (Enemy)の時は弾を削除 18 if (layerName == "Bullet (Enemy)") { 19 // 弾の削除 20 Destroy (c.gameObject); 21 } 22 23 // レイヤー名がBullet (Enemy)またはEnemyの場合は爆発 24 if (layerName == "Bullet (Enemy)" || layerName == "Enemy") { 25 26 // 【変更】 27 FindObjectOfType<Manager> ().DelayTitle (); 28 29 // 爆発する 30 spaceship.Explosion (); 31 32 // Explosionを削除 33 Destroy (gameObject); 34 35 36 37 } 38 } 39 40 //【IEnumerator DelayTitle() は、Manager.csに移行】 41 } 42}

Manager.cs

C#

1using UnityEngine; 2 3namespace CompletedAssets 4{ 5 public class Manager : MonoBehaviour 6 { 7 // …(中略) 8 9 // 【追加】 10 public void DelayTitle () 11 { 12 StartCoroutine("DelayTitleCoroutine"); 13 } 14 15 // 【追加】 16 IEnumerator DelayTitleCoroutine() 17 { 18 Debug.Log("crush"); 19 yield return new WaitForSeconds(2.0f); 20 Debug.Log("2seconds"); 21 22 GameOver (); 23 } 24 } 25}

投稿2019/07/22 07:05

編集2019/07/23 04:08
fiveHundred

総合スコア9797

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mochinotane

2019/07/22 07:20

速やかな回答ありがとうございます。 試しにDestroy (gameObject);を削除して実行するとリプレイした時に残ってしまいますがうまくタイトル画面に遷移してくれました。 恐縮ですが、非表示でオブジェクトが残ってしまうのがどうしても気になるので、別のゲームオブジェクトからコルーチンを呼び出すようにしたいのですが、どのようにするのがいいでしょうか。 参考サイト等でも構いませんのでお教えいただけると幸いです。
fiveHundred

2019/07/22 08:05

Managerに破棄するためのコルーチンを用意するのが分かりやすいと思います。
mochinotane

2019/07/23 02:55

何度も申し訳ありません。 Manager.cs内でゲームオブジェクトを破棄するコルーチンを宣言したいのですが、うまくいきません。 このサイトを参考にしているのですが仰っている内容と合致していますでしょうか。 https://qiita.com/naoK/items/55fb18bd348cfaa92708
fiveHundred

2019/07/23 04:09

多分違うかなと思います。 Playerに記載しているコルーチンやStartCoroutine()をManagerに引っ越しするという意味です。 具体例を追記しましたので、確認してください。
mochinotane

2019/07/23 04:22

お手を煩わせまして申し訳ありませんでした。 無事に解決しました。 丁寧に教えてくださって本当にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問