Search Unity

HELP, infinite loop somewhere, can't find it

Discussion in 'Scripting' started by deathbydragon, May 2, 2016.

  1. deathbydragon

    deathbydragon

    Joined:
    Mar 4, 2016
    Posts:
    54
    Hey, everything was working great, then I put in a couple new features on other scripts, and now everything is messed up. I don't know why, but I think I must be getting an infinite loop somewhere on this script. My game is about boxes that you put in bins. You used to be able to drag the boxes around, but now when you touch them, the whole editor locks up and cannot be recovered. Here is my code, please forgive its spagettiness, I literally had no clue what I was doing when I started it:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Touch : MonoBehaviour {
    5.     bool paused = false;
    6.     bool exists = true;
    7.     bool wasThis = false;
    8.     SpriteRenderer sr;
    9.     public Sprite red;
    10.     public Sprite blue;
    11.     public Sprite green;
    12.     public Sprite purple;
    13.     public Sprite orange;
    14.     GameObject rightBin;
    15.     int color;
    16.     /* public Vector2 binR;
    17.     public Vector2 binB;
    18.     public Vector2 binG;
    19.     public Vector2 binP;
    20.     public Vector2 binO; */
    21.     Vector2 binPosition;
    22.     public float toleranceX;
    23.     public float toleranceY;
    24.     bool selected; //box selected
    25.     bool isThis;
    26.     public bool followTrack = true; //for testing, can disable movement of box along track
    27.     float trackX; //X position when following track
    28.     float trackY; //Y position when following track
    29.     public float speed = 0.1f; //Speed of box while following track (Should be same as track speed for best result)
    30.  
    31.  
    32.  
    33.  
    34.     void Start () {
    35.      
    36.         GameObject go = transform.gameObject;
    37.         sr = go.GetComponent<SpriteRenderer>();
    38.  
    39.         if (sr.sprite == red) {
    40.             color = 1;
    41.             GameObject.Find("barRed").SendMessage("findBox", transform.gameObject);
    42.             GameObject.Find("barRed").SendMessage("getBin"); //must name exactly this in hirarchy!!!!!!
    43.         } else if (sr.sprite == blue) {
    44.             color = 2;
    45.             GameObject.Find("barBlue").SendMessage("findBox", transform.gameObject);
    46.             GameObject.Find("barBlue").SendMessage("getBin");  //must name exactly this in hirarchy!!!!!!
    47.         } else if (sr.sprite == green) {
    48.             color = 3;
    49.             GameObject.Find("barGreen").SendMessage("findBox", transform.gameObject);
    50.             GameObject.Find("barGreen").SendMessage("getBin");//must name exactly this in hirarchy!!!!!!
    51.         } else if (sr.sprite == purple) {
    52.             color = 4;
    53.             GameObject.Find("barPurple").SendMessage("findBox", transform.gameObject);
    54.             GameObject.Find("barPurple").SendMessage("getBin");  //must name exactly this in hirarchy!!!!!!
    55.         } else if (sr.sprite == orange) {
    56.             color = 5;
    57.             GameObject.Find("barOrange").SendMessage("findBox", transform.gameObject);
    58.             GameObject.Find("barOrange").SendMessage("getBin");  //must name exactly this in hirarchy!!!!!!
    59.         }
    60.         else { color = -1; }
    61.  
    62.        
    63.         selected = false;
    64.         isThis = false;
    65.         if (followTrack)
    66.         {
    67.             trackX = -8.5f; //Sets start X position at -8.5
    68.             trackY = Random.Range(-2.3f, -1.1f); //Sets starting Y position between -2.3 and -1
    69.             transform.position = new Vector3(trackX, trackY, 1 - trackY);
    70.         }
    71.     }
    72.  
    73.     void acceptBin(GameObject bin)
    74.     {
    75.         rightBin = bin;
    76.         binPosition = bin.transform.position;
    77.         //print(gameObject + " " + binPosition);
    78.     }
    79.     void Update () {
    80.         //test++;
    81.         if (!paused)
    82.         {
    83.             RaycastHit hit;
    84.             if (Input.touchCount > 0) //If there is a touch
    85.             {
    86.  
    87.                 Vector3 pos = Input.GetTouch(0).position; //Get its position
    88.                 //Debug.Log("Touch " + pos);
    89.  
    90.                 Ray ray = Camera.main.ScreenPointToRay(pos); //check to see if it is colliding with the box
    91.                 if (Physics.Raycast(ray, out hit)) //if it is
    92.                 {
    93.  
    94.                     hit.transform.position = new Vector2(Camera.main.ScreenToWorldPoint(pos).x, Camera.main.ScreenToWorldPoint(pos).y); //Move box to that position
    95.                     selected = true;
    96.                     if (hit.transform == transform)
    97.                     {
    98.                         isThis = true;
    99.                         wasThis = true;
    100.                         if (overBin() && exists) { rightBin.SendMessage("boxOver", transform.gameObject); }
    101.  
    102.                     }
    103.                     else { isThis = false; notThis(); }
    104.                     //Debug.Log("Something hit " + Camera.main.ScreenToWorldPoint(pos));
    105.                 }
    106.                 else { selected = false; isThis = false; notThis(); }
    107.  
    108.             }
    109.             else { selected = false; isThis = false; }
    110.             if (!isThis) { selected = false; }
    111.             if ((!selected) && (trackX < 8.5f) && followTrack) //if not selected, on the screen, and movement is enabled
    112.             {
    113.                 trackX += speed; //Change X by speed
    114.                 transform.position = new Vector2(trackX, trackY); //move box along track
    115.             }
    116.             else if (trackX > 8.5f)
    117.             {
    118.                 GameObject.Find("LifeBar").SendMessage("onLifeDown");
    119.                 Destroy(gameObject);
    120.             }
    121.             //Debug.Log(test + " " + selected);
    122.         }
    123.     }
    124.     bool overBin()
    125.     {
    126.         print("overBin");
    127.         if ((System.Math.Abs(transform.position.x - binPosition.x) <= toleranceX) && ((transform.position.y - binPosition.y) <= toleranceY))
    128.         {
    129.             return true;
    130.         }
    131.         else { return false; }
    132.     }
    133.  
    134.     //methods to be called by other gameObjects
    135.  
    136.     void speedUp()
    137.     {
    138.         speed += .01f;
    139.     }
    140.  
    141.     void speedDown()
    142.     {
    143.         speed -= .01f;
    144.     }
    145.     void checkColor(int col)
    146.     {
    147.         print("checkColor" + (wasThis));
    148.  
    149.         if ((col == color) && isThis)
    150.         {
    151.             exists = false;
    152.             while (Input.touchCount < 0) { }
    153.             GameObject.Find("LifeBar").SendMessage("onLifeUp");
    154.             Destroy(gameObject);
    155.         }
    156.     }
    157.     void notThis()
    158.     {
    159.         float time = Time.time;
    160.         while (Time.time < time + 5.0f) { }
    161.         wasThis = false;
    162.     }
    163.     void onPauseGame()
    164.     {
    165.         paused = true;
    166.     }
    167.     void onResumeGame()
    168.     {
    169.         paused = false;
    170.     }
    171. }
    172.  
    Thanks so much for looking over all of it. The messages are sent to the bins. If you think that might be where the problem is, I can post that code as well.
     
  2. Krambolage

    Krambolage

    Joined:
    Jan 22, 2013
    Posts:
    25
    Code (CSharp):
    1. void notThis()
    2.     {
    3.         float time = Time.time;
    4.         while (Time.time < time + 5.0f) { }
    5.         wasThis = false;
    6.     }
    Because time = Time.time, Time.time is always < time + 5.0f
    The empty loop goes on forever

    I must admit I didn't read the whole code, hoping there's only that issue :)
     
    Kiwasi likes this.
  3. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    There is also this gem waiting to bite

    Code (CSharp):
    1. while (Input.touchCount < 0) { }
    Although chances are it will never enter the loop, and so never lock up.

    As a general rule you always need to make sure something inside the while loop must change the condition of the loop. Empty while loops will almost always form infinite loops.
     
    Krambolage likes this.
  4. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I don't actually have any while loops, never trusted 'em.
     
    zombiegorilla and Kiwasi like this.
  5. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    I believe I read somewhere that NASA's coding standards also don't allow while loops. So you are in good company.

    I on the other hand am a sucker for while (true) loops in coroutines.
     
  6. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,332
    @deathbydragon: Time.time (and Time.deltaTime) is set at the beginning of each frame (before Update), and won't be updated before the end of the frame (before the next Update). Which is why, as @Krambolage pointed out, your while loop will go on forever.

    The easiest (to understand) solution is to save the time at which you want to start the countdown, and check how long that's since in Update.

    @BoredMormon:
    You've got different standards of coding when bugs have caused billions of dollars worth of hardware to explode in the sky, several times.

    One of the most common mistakes new programmers in Unity makes is the while-time-is-less-than infinite loop. Because of the disconnected nature of MonoBehaviours, it would be completely intuitive to someone's that new to this that they would run in parallel. A single MB locking the main thread doesn't fit with the MB as independent component idea at all.
     
  7. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Yup. In my day job most critical systems have two independent code systems and a human watching them at all times.

    My games are not so robust.
     
  8. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    But who watches the watcher?
     
    Dave-Carlile likes this.
  9. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    ... a board of international experts who can't tell the difference between feet and meters? o_O:rolleyes::cool:
     
  10. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    That's my job. ;)
     
    hippocoder likes this.
  11. deathbydragon

    deathbydragon

    Joined:
    Mar 4, 2016
    Posts:
    54
    Thanks so much guys, this has been very useful :)