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

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

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

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

Q&A

2回答

2837閲覧

while文で無限ループが起きる

ichigo_0308

総合スコア41

Unity

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

0グッド

0クリップ

投稿2020/09/12 06:32

編集2020/09/12 06:54

###<実現したいこと>
クリックされるとcount3nextという関数を実行したい。

<エラー>

その処理(エラーが起きている処理)までの処理はうまくいくが、その処理
(
public void count3()
{
while(!startflag&&gameStartB)
{
if (Startb)
{
count3next();
break;
}
}

}

)
が実行されたときにUnityがフリーズする。

<ソースコード>

C#

1using System; 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5using UnityEngine.UI; 6using UnityEngine.SceneManagement; 7 8 9public class GameScript : MonoBehaviour 10{ 11 // ロングタップ判定で使用する変数 12 float longTapTime = 2.0f; // 実行直後は、longTapTimeを過ぎると、ロングタップとみなされる 13 // 1回目の問題が終わると、タップする目標時間 14 float nowTapTime; // タップし始めてから現在までの時間 15 float safeTime = 1.0f; // 目標時間に対して許容される誤差 16 bool isLongtap; // ロングタップ中かどうか(タップする時間がlongTapTimeを越えるとtrueになる) 17 bool isLongtapclear; // ロングタップが終わったか 18 19 // ゲームで使用する変数 20 int challengecount; // 挑戦回数 21 int clearcount=0; // クリアした回数 22 int level; // 難易度 23 bool startflag = false; // ゲーム開始されていたらtrue。開始前(カウントダウン中も含む)ならfalse; 24 public string count; // 秒読みで表示する値 25 26 // デバッグ用表示テキスト 27 private Text countText; // カウントダウン表示 28 private Text Text1; // longTapTime表示(ロングタップとみなされる時間) 29 private Text Text2; // safeTime表示(タップ時間の許容誤差) 30 private Text Text3; // clearCount表示(クリアした回数) 31 private Text Text4; // nowTapTime(現在のタップ時間) 32 private Text Text5; // nowTapTime2(判定後のタップ時間) 33 private Text Text6; // 説明のText 34 public string Text1s; // longTapTime 35 public string Text2s; // safeTime 36 public string Text3s; // clearCount 37 38 public Slider slider; 39 public AudioClip clearClip; 40 public AudioClip outClip; 41 public AudioSource audioSource; 42 public bool Startb=false; 43 public bool gameStartB = false; 44 45 // Start is called before the first frame update 46 void Start() 47 { 48 49 // 表示するTextのセット 50 countText = GameObject.Find("CountText").GetComponent<Text>(); 51 Text1 = GameObject.Find("LongtapTimeText").GetComponent<Text>(); 52 Text2 = GameObject.Find("SafeTimeText").GetComponent<Text>(); 53 Text3 = GameObject.Find("clearcount").GetComponent<Text>(); 54 Text4 = GameObject.Find("NowTapTime").GetComponent<Text>(); 55 Text5 = GameObject.Find("結果text").GetComponent<Text>(); 56 57 58 level = PlayerPrefs.GetInt("level"); 59 kabe(); // レベルに合わせて許容誤差を計算 60 count3next(); // カウントダウン開始 61 62 // Textの初期値 63 Text1s = longTapTime.ToString(); 64 Text2s = safeTime.ToString(); 65 Text3s = clearcount.ToString(); 66 67 } 68 69 // Update is called once per frame 70 void Update() 71 { 72 Text1.text = "目標:"+Text1s; 73 Text2.text = "許容範囲:" + Text2s; 74 Text3.text = "clearcount: " + Text3s; 75 76 if (startflag) 77 { 78 gameStartB = true; 79 // ゲームが開始されていたら.... 80 Text1.text = "目標:" + Text1s; 81 Text2.text = "許容範囲:" + Text2s; 82 Text3.text = "clearcount: " + Text3s; 83 if (Input.GetMouseButton(0)) 84 { 85 slider.maxValue = longTapTime; 86 slider.value = nowTapTime; 87 // ボタンが押されていたら... 88 isLongtapclear = false; // ロングタップが終わっていない状態にして 89 Text1.text = "目標:" + Text1s; 90 Text2.text = "許容範囲:" + Text2s; 91 Text3.text = "clearcount: " + Text3s; 92 nowTapTime += Time.deltaTime; // 秒数をカウント 93 Text4.text = nowTapTime.ToString(); 94 95 // タップし続けた時間が規定値を超えたらロングタップとして扱う 96 if (nowTapTime >= longTapTime && !isLongtap) 97 { 98 isLongtap = true; // ロングタップしたフラグを立てる // Prefabの作成 99 Debug.Log("Long Tap"); 100 } 101 102 103 104 } 105 else if (Input.GetMouseButtonUp(0)) 106 { 107 // 「ボタンが離されたら、時間を測って、結果表示」をUpdate()内で行うため、 108 // WaitASecond()から以下の部分を移動 109 110 if (longTapTime-safeTime<nowTapTime && longTapTime + safeTime > nowTapTime && !isLongtapclear) 111 { 112 audioSource.PlayOneShot(clearClip); 113 isLongtapclear = true; 114 Debug.Log("tapclear!"); 115 longTapTime = UnityEngine.Random.Range(2, 6); 116 Text1.text = Text1s; 117 clearcount += 1; 118 Text3.text = "clearcount: " + Text3s; 119 Text1s = longTapTime.ToString(); 120 Text2s = safeTime.ToString(); 121 Text3s = clearcount.ToString(); 122 challengecount = challengecount + 1; 123 if (challengecount > 10) 124 { 125 PlayerPrefs.SetInt("clearcount", clearcount); 126 SceneManager.LoadScene("ResultScene"); 127 } 128 startflag = false; 129 count3(); 130 131 } 132 else 133 { 134 audioSource.PlayOneShot(outClip); 135 Debug.Log("OUT"); 136 challengecount = challengecount + 1; 137 if (challengecount > 10) 138 { 139 PlayerPrefs.SetInt("clearcount", clearcount); 140 SceneManager.LoadScene("ResultScene"); 141 } 142 count3(); 143 } 144 145 146 // クリックを終えたら初期化 147 nowTapTime = 0; 148 isLongtap = false; 149 } 150 if(Input.GetMouseButtonUp(0)&&!isLongtap) 151 { 152 153 startflag = false; 154 count3(); 155 } 156 } 157 if (Input.GetMouseButtonDown(0) && !startflag&&gameStartB) 158 { 159 Startb = true; 160 } 161 else if(!startflag&&gameStartB) 162 { 163 Startb = false; 164 } 165 } 166 public void kabe() 167 { 168 safeTime = 1.0f / (level + 1); 169 safeTime *= 1.5f; 170 Debug.Log(safeTime); 171 } 172 public void count3() 173 { 174 while(!startflag&&gameStartB) 175 { 176 if (Startb) 177 { 178 count3next(); 179 break; 180 } 181 } 182 183 184 } 185 public void count3next() 186 { 187 count = "3"; 188 countText.text = count; 189 Invoke("count2", 1); 190 } 191 public void count2() 192 { 193 count = "2"; 194 countText.text = count; 195 Invoke("count1", 1); 196 } 197 public void count1() 198 { 199 200 count = "1"; 201 countText.text = count; 202 Invoke("start", 1); 203 } 204 public void start() 205 { 206 count = "start!"; 207 countText.text = count; 208 Invoke("startsetting", 1); 209 } 210 public void startsetting() 211 { 212 startflag = true; 213 214 } 215 //IEnumerator WaitASecond() 216 //{ 217 // yield return new WaitForSeconds( 1f ); 218 219 // print( ( longTapTime - safeTime < nowTapTime ) + " : " + ( longTapTime + safeTime > nowTapTime ) + " : " + !isLongtapclear ); 220 // if ( ( longTapTime - safeTime < nowTapTime ) 221 // && ( longTapTime + safeTime > nowTapTime ) && !isLongtapclear ) { 222 // isLongtapclear = true; 223 // Debug.Log( "tapclear!" ); 224 // longTapTime = UnityEngine.Random.Range( 2, 6 ); 225 // Text1.text = Text1s; 226 // clearcount += 1; 227 // Text3.text = "clearcount: " + Text3s; 228 // Text1s = longTapTime.ToString(); 229 // Text2s = safeTime.ToString(); 230 // Text3s = clearcount.ToString(); 231 232 // } 233 // else { 234 // Debug.Log( "OUT" ); 235 // } 236 //} 237 //IEnumerator MyLoop() 238 //{ 239 // for ( isLongtap = false; ; ) { 240 // yield return new WaitForSeconds( 0.2f ); 241 // } 242 // StartCoroutine( "WaitASecond" ); 243 //} 244} 245

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

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

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

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

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

y_waiwai

2020/09/12 06:41

その処理とはどの処理? 無限ループとはコードのどの部分で起きる? あまりにも説明不足ですぜ
ichigo_0308

2020/09/12 06:53

すみません。編集します。
guest

回答2

0

演算子の優先順位
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/operators/#operator-precedence

演算子の優先順位に従って&&より先に!が 処理されるから意図せず while (true && true)と評価されている可能性があります。

演算子の優先順位を変更するには先に評価させたい式を()で括ります。

例えば A && B の結果全体を真偽反転させたいのであれば !(A && B) と記述します。

(あくまで演算子の優先順位を理解しようって話で、そう書いたからといってあなたの意図したとおりに動くかはわかりません)

投稿2020/09/13 11:52

編集2020/09/13 11:54
tor4kichi

総合スコア763

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

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

0

このようにすればフリーズせずに原因を絞れると思います。

C#

1public void count3() 2{ 3 int brk = 100; 4 while(!startflag&&gameStartB) 5 { 6 if (Startb) 7 { 8 count3next(); 9 break; 10 } 11 12 brk--; 13 if( brk==0 ){ 14 Debug.LogError( "startflag:" + startflag + "\ngameStartB:" + gameStartB + "\nStartb:" + Startb ); 15 Debug.Break(); 16 break; 17 } 18 } 19}

投稿2020/09/12 08:07

i_zna

総合スコア198

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

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

ichigo_0308

2020/09/12 23:33

while文の中で Debug.LogErrorを実行してみて、コンソールを見ましたが、startflagがfalse,gameStartBがtrueと出ました。それであってるのですが、なぜ無限ループするのででしょうか?
i_zna

2020/09/13 03:11

while文は()の中がtrueである限り処理を繰り返します。Startbで脱出させたいみたいですが、Startbがfalseだったときの処理が何もないので永久に空回りします。
ichigo_0308

2020/09/13 04:52

すみません。説明が足りませんでした。trueになるまで待つというスクリプトを書きたくて、このようなスクリプトを書きました。
i_zna

2020/09/13 11:14

Unityが処理の終了を待っているからです。 Update()は毎フレーム呼ばれているので、待つ目的ならそもそもループ文は必要ありません。 失礼ですがかなり基礎的なことですので、このような複雑なコードや非同期処理に触れるのはまだ早いかと…
ichigo_0308

2020/09/14 06:37

ということは、Update内でループ分は書かなくてよいといことですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問