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

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

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

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

while

Whileは多くの言語で使われるコントロール構造であり、特定の条件が満たされる限り一連の命令を繰り返し実行します。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Unity

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

Q&A

解決済

2回答

3121閲覧

【Unity】コルーチンのwhileループを出るときにフリーズする

justblack

総合スコア4

C#

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

while

Whileは多くの言語で使われるコントロール構造であり、特定の条件が満たされる限り一連の命令を繰り返し実行します。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Unity

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

0グッド

0クリップ

投稿2020/02/25 13:06

編集2020/02/28 05:06

Unityで行き詰ったので教えてください。

趣味でRPG作ってます。アイテムドロップ処理を考えてみましたが、どうもうまくいきません。
コルーチンAのwhile内でコルーチンBを待ち、コルーチンBではwhileでboolの判定をしています。
コルーチンBのwhileが抜ける際、フリーズします。
なぜでしょうか?

C#

1public static bool click = false; 2public static string[] strArray = new string[]{"text", "t", ""}; 3~~~ 4public static IEnumerator CoroutineA(MonoBehaviour monoBehaviour) 5{ 6 ~~~ 7 Debug.Log("敵を倒した"); //出力される 8 yield return monoBehaviour.StartCoroutine(CoroutineB()); 9 Debug.Log("check 0"); //出力される 10 11 str = ""; 12 while(str == "") 13 { 14 int i = Random.Range(0, strArray.Length); 15 str = strArray[i]; 16 if(str != "") 17 { 18 Debug.Log("str:あたり"); //出力される 19 yield return monoBehaviour.StartCoroutine(CoroutineB()); 20 Debug.Log("check 3"); //出力されない 21 break; 22 } 23 else 24 { 25 Debug.Log("str:はずれ"); 26 } 27 yield return null; 28 } 29} 30 31//メッセージスキップ待機 32public static IEnumerator CoroutineB() 33{ 34 click = false; 35 while(!click) 36 { 37 Debug.Log("check 1"); //出力される 38 yield return null; 39 } 40 Debug.Log("check 2"); //フリーズする 41 yield break; 42} 43 44//ボタンにアタッチしているメソッド(メッセージスキップボタン) 45public void ButtonClick() 46{ 47 click = true; 48} 49

試したこと

continueを使い、基本的にwhileを出るようにしましたが、フリーズしてしまいました。

C#

1~~~ 2 str = ""; 3 while(str == "") 4 { 5 int i = Random.Range(0, strArray.Length); 6 str = strArray[i]; 7 if(str != "") 8 { 9 Debug.Log("str:あたり"); //出力される 10 yield return monoBehaviour.StartCoroutine(CoroutineB()); 11 Debug.Log("check 3"); //出力されない 12 break; 13 } 14 else 15 { 16 Debug.Log("str:はずれ"); 17 if(条件:特殊アイテム装備){ continue; } 18 } 19 yield return null; 20 break; 21 } 22} 23 24//メッセージスキップ待機 25public static IEnumerator CoroutineB() 26{ 27 click = false; 28 while(!click) 29 { 30 Debug.Log("check 1"); //出力される 31 yield return null; 32 if(!click){ continue; } 33 break; 34 } 35 Debug.Log("check 2"); //フリーズする 36 yield break; 37} 38 39//ボタンにアタッチしているメソッド(メッセージスキップボタン) 40public void ButtonClick() 41{ 42 click = true; 43}

フリーズするコルーチンBを外しましたが、フリーズしてしまいました。

C#

1~~~ 2 str = ""; 3 while(str == "") 4 { 5 int i = Random.Range(0, strArray.Length); 6 str = strArray[i]; 7 if(str != "") 8 { 9 Debug.Log("str:あたり"); //出力されず、フリーズする 10 //yield return monoBehaviour.StartCoroutine(CoroutineB()); 11 Debug.Log("check 3"); //出力されない 12 break; 13 } 14 else 15 { 16 Debug.Log("str:はずれ"); 17 } 18 yield return null; 19 } 20} 21~~~

模擬的に別のwhileループを作りましたが、模擬ループでもループを出る際にフリーズしました。

C#

1~~~ 2 int w = 0; 3 while(true) 4 { 5 Debug.Log("check while: " + w); //1秒毎に出力され、"check while: 4" を出力後、フリーズする。 6 yield return new WaitForSeconds(1f); 7 w++; 8 if(w < 5){ continue; } 9 break; 10 } 11 12 str = ""; 13 while(str == "") 14 { 15 int i = Random.Range(0, strArray.Length); 16 str = strArray[i]; 17 if(str != "") 18 { 19 Debug.Log("str:あたり"); //出力されず、フリーズする 20 //yield return monoBehaviour.StartCoroutine(CoroutineB()); 21 Debug.Log("check 3"); //出力されない 22 break; 23 } 24 else 25 { 26 Debug.Log("str:はずれ"); 27 } 28 yield return null; 29 } 30} 31~~~

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

Unity 2019.1.0f2

質疑への回答

Q1.
CoroutineAを開始するときに渡しているmonoBehaviourに対して、どこかでDestroyを行っているスクリプトはないでしょうか?

A1.
確認しましたが、そのようなスクリプトはありませんでした。
エンカウント時に当該のmonoBehaviourを付与しているボタンを初期化のため破棄をしていますが、コルーチンAを開始するためのボタンであり、処理の途中で破棄するようにはしていません。

Q2.
「フリーズする」とはどのような状態のこと言うか。

A2.
Unityの強制終了が必要となるフリーズです。
"str:あたり"が1回出力され、その後、メッセージスキップボタンを押すまで"check 1"が出力され続けますが、ここまでは作った通り動いています。ボタンを押したとき、"check 2"は出力されず、Unityのプレイボタンを押そうとしても押せない状態に陥ります。

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

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

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

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

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

Bongo

2020/02/26 22:05

CoroutineAを開始するときに渡しているmonoBehaviourに対して、どこかでDestroyを行っているスクリプトはないでしょうかね? CoroutineBは引数として渡されたmonoBehaviourを介して実行されているはずですので、どこかでmonoBehaviourが破壊されると続行できなくなってしまう気がします。
Bongo

2020/02/27 18:02

最初に確認しておくべきことを後出しにしてしまって申し訳ないのですが、「フリーズする」とおっしゃるのは下記のどの症状に近いでしょうか? ・2回目のコルーチンBを開始すると「check 1」が表示された後にUnity自体が応答しなくなり、プレイボタンを押してもプレイモードを停止することができず、Unityを強制終了しないといけなくなる。 ・2回目のコルーチンBを開始すると「check 1」が表示されて以降はコンソールに新しいメッセージは表示されなくなり、メッセージスキップボタンを押しても反応はないが、プレイボタンを押すと通常通りプレイモードが終了する。 ・2回目のコルーチンBを開始すると「check 1」が延々と表示され続け(コンソールの「Collapse」ボタンがオンなら「check 1」メッセージの右端のカウントがどんどん増え続け)、メッセージスキップボタンを押しても反応はないが、プレイボタンを押すと通常通りプレイモードが終了する。
guest

回答2

0

自己解決

解決しました。
結論、無限ループが発生していました。

発生箇所はコルーチンAでもコルーチンBでもありませんでした。
コルーチンAが完了した後、ずっと正常に動作しており、コルーチンEあたりで抜け出せないループがありました。

Aの完了後は目で見える戻り値が無かったために、まるでAやBで発生しているように見えたようです。

当該箇所を修正後は、フリーズすることなく動作しました。

回答および質問してくださった方々ありがとうございました。
お騒がせしました。

C#

1public static IEnumerator CoroutineA(MonoBehaviour monoBehaviour) 2{ 3 //じつは完了してた 4} 5 6~~~ 7 8List<string> ListA = new List<string>() { "" , "text", "txt"}; 9List<string> ListB = new List<string>() { "Text" }; 10public static IEnumerator CoroutineE(MonoBehaviour monoBehaviour) 11{ 12 int index = 0; 13 do 14 { 15 index = Random.Range(0, ListB.Count); //←参照したいリストと異なるリストを参照 16 //yield return null;すら無い 17 } while (ListA[index] == ""); 18} 19

投稿2020/02/28 07:52

justblack

総合スコア4

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

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

0

BのWhileの中にbreakポイントが無いからだと思います。

whileの条件を満たし続けているので、そもそも抜けていないかと。
yield return null はコルーチンの処理を1フレーム中断する命令なので、永遠にwhile内を繰り返しているんじゃないでしょうか。

あとAのwhile(str == "")にもif(str != "")の場合にしかbreakがないので、yield return nullの部分をbreakにして、{}の外側にyield return nullを書かないとAもフリーズする要素が発生するかと。

投稿2020/02/26 08:27

Y0241-N

総合スコア1066

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問