Search Unity

Resolved Unity freezes when using while loop

Discussion in 'Scripting' started by ArthurHaleta, Feb 7, 2022.

  1. ArthurHaleta

    ArthurHaleta

    Joined:
    Dec 24, 2021
    Posts:
    44
    I want to make a sort-of troop placing system, so whenever I click the button, I get to choose where to place the troop and click to place it in that fixed position; however, Unity just freezes every time I click it, and I don't know what to do. Thanks!

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class placeTroop : MonoBehaviour
    6. {
    7.     public GameObject troop;
    8.     bool place;
    9.  
    10.     public void clicked()
    11.     {
    12.         GameObject placedTroop = Instantiate(troop, Camera.main.ScreenToWorldPoint(Input.mousePosition), Quaternion.identity);
    13.         place = false;
    14.  
    15.         while (!place)
    16.         {
    17.             placedTroop.transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    18.  
    19.             if (Input.GetMouseButtonDown(0))
    20.             {
    21.                 place = true;
    22.             }
    23.         }
    24.     }
    25. }
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    Unity is singlethreaded (mostly), which means that as long as your function is running, no other code will execute. So clicked() is called, it enters that loop, and then nothing else in the engine runs until the loop exits. In this case, that is important because input is not processed either, so GetMouseButtonDown is never going to be true as long as you're in this loop.

    What you can do is have clicked() call a coroutine. Coroutines run like regular code until they reach a line that says "yield return null;" at which point they freeze execution, and then the Unity engine will resume that execution in the next frame. So you can put that line inside your while loop and the game will keep running while you wait for the button to click.
    Code (csharp):
    1. public void clicked() {
    2.      StartCoroutine(clickCoroutine());
    3. }
    4.  
    5. private IEnumerator clickCoroutine() {
    6.         GameObject placedTroop = Instantiate(troop, Camera.main.ScreenToWorldPoint(Input.mousePosition), Quaternion.identity);
    7.         place = false;
    8.  
    9.         while (!place)
    10.         {
    11.             placedTroop.transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    12.  
    13.             if (Input.GetMouseButtonDown(0))
    14.             {
    15.                 place = true;
    16.             }
    17.            yield return null;
    18.         }
    19. }