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

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

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

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

Q&A

解決済

2回答

1608閲覧

画面を一定時間停止後に画面遷移させる処理がうまくいかない

RTera

総合スコア11

Unity

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

0グッド

0クリップ

投稿2018/08/23 23:03

【やりたいこと】
アクションゲームのゲームオーバー処理で、画面全体を一定時間停止させた後、
後続の処理を再開させたい。(ここでは画面遷移)

【困っていること】
下記コードのように、Time.timeScale = 0.0f; で停止させた後、
コルーチン内でWait処理を実行させた後、
Time.timeScale = 1.0f; で画面更新を戻すロジックを作りましたが、
下記コメント記述のように、うまくいかず、
Time.timeScale = 1.0f; を付ける適切な場所がわかりません。

Time.timeScale = 1.0f; をつけた状態だと、画面が一時停止しなくなります。

ちなみに、コルーチンを使ったやり方については、いろいろと情報サイトを調べて試してみましたが、うまくいっていません。

どなたかご教示お願い致します。m(_ _)m

記載の不備等ありましたら、ご質問頂ければ、補足説明します。

【Unityのバージョン】
unity2017_1.0f3

using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.SceneManagement; public class GameManager : MonoBehaviour { // … 中略 … // ゲームオーバー処理 public void GameOver () { // … 中略 … Time.timeScale = 0.0f; StartCoroutine("PauseMinites", 2.0f); Invoke("GoBackStageSelect", 2.0f); // ↓ これを付けると、シーンが一時停止しなくなる。 // ↓ 削除すると、シーンが停止したままとなる。 Time.timeScale = 1.0f; } // ステージ選択シーンに戻る void GoBackStageSelect () { SceneManager.LoadScene ("StageSelectScene"); } // 一定時間停止処理 IEnumerator PauseMinites(float sec) { Debug.Log("PauseMinites呼び出し"); yield return new WaitForSeconds(sec); Debug.Log("Wait後、timeScaleを1に設定。"); Time.timeScale = 1.0f; } }

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

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

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

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

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

guest

回答2

0

ベストアンサー

Time.timeScaleは単なる一時停止ではなく、**「Unity内の時間の流れ設定(倍率)」**です。
つまりTime.timeScale = 0.0f;は「時間の流れを0倍にする=時間を止める」ということなので、WaitForSecondsやInvokeの時間測定は止まります。
(時間の流れが止まっているので「○秒後」も来ることが無い)

Coroutine自体が止まっているわけではないので、
yield return new WaitForSeconds(sec);の部分を
for (int i = 0; i < 100; i++) { yield return null; }
とかにすれば一応計測は可能です。
yield return null;は1フレーム待つのと同じ処理。フレームの更新自体は行われている為)
なお、Updateも止まりませんが、Time.deltaTimeは0になるので、時間計測時はTime.realtimeSinceStartupなどを使ってください。

Unityの一時停止で止まるもの、止まらないもの【Time.timeScale】
Time.timeScale に左右されない時間を使う【Tips】

投稿2018/08/24 00:49

sakura_hana

総合スコア11425

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

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

RTera

2018/08/26 10:08

ご教示頂き、ありがとうございました。 とりあえずではありますが、下記のように自己解決しました。 シーンの一時停止処理の実装については、個人的には今後の課題とさせていただきます。
guest

0

上記回答頂いたように、次の通りに実装して試してみましたが、
停止した状態のまま、再開できませんでした。

///GameManager.cs public class GameManager : MonoBehaviour { // 中略 // ゲームオーバー処理 public void GameOver () { textGameOver.SetActive (true); PauseMinites(3.0f); Invoke("GoBackStageSelect", 0.0f); } // ステージセレクトシーンに戻る public void GoBackStageSelect () { SceneManager.LoadScene ("StageSelectScene"); } // 一定時間停止処理 void PauseMinites(float sec) { Debug.Log("PauseMinites呼び出し"); Time.timeScale = 0.0f; for (lastRealTime = 0.0f, realDeltaTime = 0.0f; sec > realDeltaTime; ) { Debug.Log("realtimeSinceStartup呼び出しループ内"); // 【???】このループ処理から脱出できていないと思われる。 CalcRealDeltaTime(); } Time.timeScale = 1.0f; Debug.Log("Wait後、timeScaleを1に設定。"); } //現実時間基準で経過時間を計算する void CalcRealDeltaTime() { if (lastRealTime == 0) { lastRealTime = Time.realtimeSinceStartup; } realDeltaTime = Time.realtimeSinceStartup - lastRealTime; lastRealTime = Time.realtimeSinceStartup; } }

シーン全体を一時停止する代わりに、停止させたい、(ボールの)オブジェクトのみ停止させる実装方針に変更しました。
具体的には、次のように、RidgeBody2Dの velocity(位置移動)と、Z軸方向の回転(Rotation)を停止させるようにしました。

///GameManager.cs public class GameManager : MonoBehaviour { // 中略 // ゲームオーバー処理 public void GameOver () { textGameOver.SetActive (true); Invoke("GoBackStageSelect", 3.0f); } // ステージセレクトシーンに戻る public void GoBackStageSelect () { SceneManager.LoadScene ("StageSelectScene"); } } /// PlayerManager.cs public class PlayerManager : MonoBehaviour { private Rigidbody2D rbody; // プレイヤー制御用rigidbody2D void Start () { rbody = GetComponent<Rigidbody2D> (); } // 衝突処理 void OnTriggerEnter2D(Collider2D col) { //停止したBombに衝突時、又は移動範囲外に出た場合 if ("Bomb".Equals(col.gameObject.tag) || "Trap".Equals(col.gameObject.tag)) { //ボール\停止処理 StopPlayer(); gameManager.GetComponent<GameManager>().GameOver(); } } //ボール移動・回転停止および重力無効化処理 void StopPlayer() { rbody.velocity = Vector2.zero; rbody.freezeRotation = true; rbody.isKinematic = true; } }

投稿2018/08/26 10:16

RTera

総合スコア11

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

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

sakura_hana

2018/08/27 07:48

再開出来なかった方のコードですが、 CalcRealDeltaTime()内の最後の「lastRealTime = Time.realtimeSinceStartup;」のせいで、realDeltaTimeが「このメソッドの前回呼び出しからの経過時間」になっています。 なのでPauseMinites()のsecよりも大きくなることはありません。 こいつは上記の「lastRealTime = Time.realtimeSinceStartup;」を削除すれば正常に動作します。 ちなみにPauseMinites()をvoidにしておくと、forループが1秒間に物凄い回数回ります。 (PC上で計測したら1回あたり0.0002秒ぐらいで回ります) void PauseMinites(float sec) を IEnumerator PauseMinites(float sec)に変えて forの中に yield return null; を刺すと1フレーム(0.016秒とか)毎の回転になるので余計な負荷を掛けさせないかと思います。
RTera

2018/08/29 14:39

コメントが遅くなりました。 補足説明して頂き、ありがとうございました。 上記のように、「lastRealTime = Time.realtimeSinceStartup;」を削除して、正常に動作することを確認しました。 ちなみに、後半の説明のように、IEnumerator と yield return null; を使うと、 なぜか、Waitせずに画面遷移してしまい、ステージ選択画面から再度同じステージを選択しても、画面が止まったまま動かない、という状況です。 しかし、回答にありました「Time.realtimeSinceStartup を使う」という重要なヒントと参考URLをご教示頂いたので、最初の回答及び、上記のコメントをベストアンサーとさせて頂きます。 追伸 コルーチンと、フレームのUpdate 間の処理の流れが未だによくわかっていません。。。(。。) 今後も学習して、コルーチンや、画面更新処理をうまく使いこなせるようになりたいと思います。
sakura_hana

2018/08/30 01:05

>Waitせずに画面遷移してしまい、ステージ選択画面から再度同じステージを選択しても、画面が止まったまま動かない 書き方悪かったですね。コルーチンに変更しただけだとそういう動きになります。 void Do () { 処理1; StartCoroutine(コルーチン); 処理2; } 上記の場合、通常のスクリプトと同様に「処理1実行→コルーチンの呼び出し(※呼び出されるだけで待たない)→処理2実行」のように、待機無しで進みます。(=コルーチン内の処理と、処理2が並行で実行される) なので待機したい場合は処理2をコルーチンの内部に入れるか、この一連の処理を行っているメソッドもコルーチン化してyieldを使います。 IEnumerator Do () { 処理1; yield return コルーチン; //コルーチンが終わるまで待機 処理2; } >コルーチンと、フレームのUpdate間の処理の流れ 「全く別々に動く」と思ってください。両者に関連性は無いです。 ただフレームを時間軸のベースにしているのは共通です。 以下を見ると処理の流れが分かりやすいかと思います。ご参考までに。 https://docs.unity3d.com/ja/current/Manual/ExecutionOrder.html
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問