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

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

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

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

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

Q&A

解決済

2回答

1356閲覧

StartCoroutineで呼び出せない。

YukioMaki

総合スコア21

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

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

0グッド

0クリップ

投稿2017/11/12 03:47

UnityでC#を使って作っています。
コールチンを使ってsound Play();を30秒ごとに実行させたいのですが、StartCoroutine(Sleep));からIEnumerator Sleep()に移行しません。
そのためにaddText textの表示が 1 、30秒後に 2 を表示したいのですが、すぐに 2 を表示してしまいます。
また、このスクリプトで 1 、30秒後に 2 を表示出来るのかも分からないので訂正箇所を教えてもらえますか。
下記にそのスクリプトを添えて置きます。
・・・・
void Update()
{
ST = GameObject.Find("Stage");
scripta1 = ST.GetComponent<Stage2>();
T = scripta1.total;
if (Input.anyKey)
{
if (T < 0)
StartCoroutine(Sleep());

{ addText.text = " " + 1.ToString(); sound.PlayWide(); Debug.Log("add"); } if (T < 1) StartCoroutine(Sleep()); { addText.text = " " + 2.ToString(); sound.PlayWide(); Debug.Log("add"); } } } IEnumerator Sleep() { yield return new WaitForSeconds(30.f); }

}
*T=5と考えてください。

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

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

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

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

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

guest

回答2

0

ベストアンサー

StartCoroutine(実行したい内容) は、実行したい内容を「やっておいてね!」と言って、すぐ次の行に進んでしまうので、質問のような挙動になります。

また、すぐに次の行に進んでしまうので、複数回StartCoroutine()で待つ処理を呼び出しても、何回か連続して待つ(30秒待ったあとに、さらに30秒待つ)という処理にはなりません。

質問にある仕様を正しく理解できているか分かりませんが、
0. 「1」を表示する
0. 30秒待つ
0. 「2」を表示する
0. 30秒待つ
・・・

というような挙動を期待している場合は、StartCoroutine()で呼び出すSleep()側で、WaitForSeconds()とaddText.text = " " + 1.ToString();・・・のループを処理する必要があるかと思います。
また、引数としてループ回数などを渡す必要もあるかと思います。

Unity スクリプトリファレンス MonoBehaviour.StartCoroutine
https://docs.unity3d.com/jp/540/ScriptReference/MonoBehaviour.StartCoroutine.html
にあるサンプルを参考にするとよいかと思います。


追記:
質問にあるコード(抜粋)を読みやすく(バグを仕込みにくく)書き直してみると、次のようになっているかと思います。
不等号の向きなどが期待している動作と異なっているような気がしますので、一旦見直してみては?

if (T < 0) { StartCoroutine(Sleep()); } addText.text = " " + 1.ToString(); if (T < 1) { StartCoroutine(Sleep()); } addText.text = " " + 2.ToString();

投稿2017/11/12 05:36

toris-birds

総合スコア122

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

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

YukioMaki

2017/11/15 06:33

toris-birdsさん回答ありがとうございます。 書かれていたサンプルを参考に下記のスクリプトに書き換えたところ、[ 'void' は反復子インターフェイス型ではないため、'Addsistem.Update()' の本体は反復子ブロックにできません。]エラーになりました。 訂正を教えていただきたいのですが、 ・・・ void Start() { addText.text = " "; sound = GameObject.Find("SoundManager").GetComponent<SoundManager>(); } void Update() { ST = GameObject.Find("Stage"); scripta1 = ST.GetComponent<Stage2>(); T = scripta1.total; if (Input.anyKey) { StartCoroutine("DoSomething", 2.0f); yield return new WaitForSeconds(1); StopCoroutine("DoSomething"); if (T < 0) { addText.text = " " + 1.ToString(); sound.PlayWide(); } if(T<1) StartCoroutine("DoSomething", 2.0f); yield return new WaitForSeconds(1); StopCoroutine("DoSomething"); { addText.text = " " + 1.ToString(); sound.PlayWide(); } } } IEnumerator DoSomething(float someParamerter) { while (true) { print("DoSomething Loop"); yield return null; } } } void Start() { addText.text = " "; sound = GameObject.Find("SoundManager").GetComponent<SoundManager>(); } void Update() { ST = GameObject.Find("Stage"); scripta1 = ST.GetComponent<Stage2>(); T = scripta1.total; if (Input.anyKey) { StartCoroutine("DoSomething", 2.0f); yield return new WaitForSeconds(1); StopCoroutine("DoSomething"); if (T < 0) { addText.text = " " + 1.ToString(); sound.PlayWide(); } if(T<1) StartCoroutine("DoSomething", 2.0f); yield return new WaitForSeconds(1); StopCoroutine("DoSomething"); { addText.text = " " + 1.ToString(); sound.PlayWide(); } } } IEnumerator DoSomething(float someParamerter) { while (true) { print("DoSomething Loop"); yield return null; } } } void Start() { addText.text = " "; sound = GameObject.Find("SoundManager").GetComponent<SoundManager>(); } void Update() { ST = GameObject.Find("Stage"); scripta1 = ST.GetComponent<Stage2>(); T = scripta1.total; if (Input.anyKey) { StartCoroutine("DoSomething", 2.0f); yield return new WaitForSeconds(1); StopCoroutine("DoSomething"); if (T < 0) { addText.text = " " + 1.ToString(); sound.PlayWide(); } if(T<1) StartCoroutine("DoSomething", 2.0f); yield return new WaitForSeconds(1); StopCoroutine("DoSomething"); { addText.text = " " + 1.ToString(); sound.PlayWide(); } } } IEnumerator DoSomething(float someParamerter) { while (true) { print("DoSomething Loop"); yield return null; } } }
toris-birds

2017/11/15 07:39 編集

YukioMakiさん まず、質問やコメントは、Markdownを使ってフォーマットしましょう。 インデントも抜けているので、非常に読みにくいです。 また、同一のコードが繰り返しペーストされているようです。 投稿、コメント後には、一度内容を見直しましょう。 ・・・と思ったら、コメント欄は、Markdownがうまく動作しないみたいですね。 ざっくり打ち直しておきました。質問にあるコードと若干仕様が変わっているかもしれません。 (最初の「1」を一定時間待った後に出す仕様になっています。) また、動作確認、コンパイル等通していないので、typo等あるかもしれませんが、ご容赦を。 ---- ```c# void Start() { addText.text = " "; sound = GameObject.Find("SoundManager").GetComponent<SoundManager>(); } void Update() { ST = GameObject.Find("Stage"); scripta1 = ST.GetComponent<Stage2>(); T = scripta1.total; if (Input.anyKey) { StartCoroutine(DoSomething(T)); } } IEnumerator DoSomething(int T) { for (int i = 0; i < T; i++) { yield return new WaitForSeconds(1); // 指定時間待つ String text = String.format(" {0}", i); // " " + i.ToString(); でも作れると思いますが・・ print(text); sound.PlayWide(); // (UIスレッドとは別のスレッドで動作するはずなので)ここで呼ぶと例外が発生するかと思います。 // 必要な場合は、別途。 // addText.text = text; } } ```
YukioMaki

2017/11/18 14:58

toris-birdsさんコードを書き直し構想どうりに動くようになりました。 ありがとうございます。 また、ご指導よろしくお願いします。
toris-birds

2017/11/20 03:51 編集

@YukioMaki さん 動くようになったようで、よかったです。 今回の質問の範囲からは外れますが、Update()は、設定したフレームレート(例えば60FPS)などに応じて、1秒間に数10回呼び出されるかと思います。また、キーは押してすぐ手を離したとしても、0.1秒程度は押したままになっているかと思います。 なので、Update()の中でキー入力に応じて呼ばれる処理は、1回のキー入力でかなりの回数呼ばれることになるかと思います。(似たようなタイミングで同じ処理が走るので、表示上は問題なさそうに見えるかもしれません。) 実装に慣れて来たら、その当たりを考慮して設計を変えた方がよいかと思います。 参考になれば。
guest

0

サウンドのPlayと30秒待つをコルーチン内で行えばできると思います。

C#

1IEnumerator SoundLoop() 2{ 3 while(true) 4 { 5 // サウンド再生 6 sound.PlayWide(); 7 8 // 30秒待つ 9 yield return new WaitForSeconds(30.f); 10 } 11}

投稿2017/11/12 05:28

StudioAres

総合スコア127

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

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

toris-birds

2017/11/12 05:41 編集

おそらく、質問者が想定している動作は、yield return new WaitForSeconds(30.f); sound.PlayWide(); の順かと思います。
YukioMaki

2017/11/15 06:25 編集

StudioAresさん回答ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問