Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Unity freeze...

Discussion in 'Scripting' started by jister, Sep 14, 2016.

  1. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,749
    hey i'm stuck with unity freezing up without giving any errors or info why...
    I'm generating a growing mesh, in short it: generates a new triangle, adds it to a list, combine the meshes it the list, turn of the gameObject of the new triangle.

    At first i thought it was a performance issue, but the freeze happens after any amount of triangles are generated...

    there's a tool that lets you choose around which triangle the growing should continue, just a raycast to the triangle index... the freeze happens mostly after selecting a new triangle but at random moments.
    I have two Coroutines running, one for the growing of the tetrahedral (so one vert moving and updating triangles) and one to listen to the mouse click for choosing a new triangle.

    code is still messy proof of concept... maybe i should clean it up first :)

    Code (CSharp):
    1. IEnumerator Grow()
    2.     {
    3.         float count = growTime;
    4.         while (count > 0)
    5.         {
    6.             Debug.DrawRay (v, growDirection * 4f);
    7.  
    8.             v+=growDirection*Time.deltaTime;
    9.             count -= growRate;
    10.             Builder.RecalculateTriangles (allObjects, v);
    11.             yield return new WaitForSeconds (growRate);
    12.         }
    13.         CombineMeshes ();
    14.     }
    15.  
    16.     public void CombineMeshes()
    17.     {
    18.        
    19.         CombineInstance[] combine = new CombineInstance[allObjects.Count];
    20.         int i = 0;
    21.         while (i < allObjects.Count) {
    22.             combine[i].mesh = allObjects[i].GetComponent<MeshFilter>().sharedMesh;
    23.             combine[i].transform = allObjects[i].transform.localToWorldMatrix;
    24.             allObjects[i].gameObject.SetActive(false);
    25.             i++;
    26.         }
    27.         colors.Clear ();
    28.         foreach (CombineInstance c in combine)
    29.         {
    30.             Mesh m = c.mesh;
    31.             for (int j = 0; j < m.vertices.Length; j+=3) {
    32.                 if (rndmColors) {
    33.                     colors.Add (new Color (Random.Range (0.0f, 1.0f),
    34.                         Random.Range (0.0f, 1.0f),
    35.                         Random.Range (0.0f, 1.0f)));
    36.                     colors.Add (new Color (Random.Range (0.0f, 1.0f),
    37.                         Random.Range (0.0f, 1.0f),
    38.                         Random.Range (0.0f, 1.0f)));
    39.                     colors.Add (new Color (Random.Range (0.0f, 1.0f),
    40.                         Random.Range (0.0f, 1.0f),
    41.                         Random.Range (0.0f, 1.0f)));
    42.                 } else {
    43.                     colors.Add (new Color (Mathf.Abs (m.vertices [j].normalized.x),
    44.                         Mathf.Abs (m.vertices [j].normalized.y),
    45.                         Mathf.Abs (m.vertices [j].normalized.z)));
    46.                     colors.Add (new Color (Mathf.Abs (m.vertices [j].normalized.x),
    47.                         Mathf.Abs (m.vertices [j].normalized.y),
    48.                         Mathf.Abs (m.vertices [j].normalized.z)));
    49.                     colors.Add (new Color (Mathf.Abs (m.vertices [j].normalized.x),
    50.                         Mathf.Abs (m.vertices [j].normalized.y),
    51.                         Mathf.Abs (m.vertices [j].normalized.z)));
    52.                 }
    53.             }
    54.         }
    55.         Mesh newMesh = transform.GetComponent<MeshFilter> ().mesh;
    56.         transform.GetComponent<MeshFilter> ().mesh = new Mesh();
    57.         transform.GetComponent<MeshFilter> ().mesh.CombineMeshes(combine);
    58.         MeshCollider mc = gameObject.GetComponent<MeshCollider> ();
    59.         mc.sharedMesh = newMesh;
    60.        
    61.         transform.GetComponent<MeshFilter> ().mesh.colors = colors.ToArray ();
    62.         next = Random.Range (0, currentObjects.Count);
    63.         mesh = currentObjects [next].GetComponent<MeshFilter> ().sharedMesh;
    64.         while(Physics.Raycast (Vector.GetCentroid(mesh.vertices), mesh.normals [0], 2f))
    65.         {
    66.             next = Random.Range (0, currentObjects.Count);
    67.             mesh = currentObjects [next].GetComponent<MeshFilter> ().sharedMesh;
    68.         }
    69.         Debug.DrawRay (Vector.GetCentroid(mesh.vertices), mesh.normals [0] * 4f);
    70.         growDirection = mesh.normals [0];
    71.         BuildVisah (mesh);
    72.     }
    and the tool
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using System.Linq;
    6.  
    7. [System.Serializable]
    8. public class ExpandInDirection : Control
    9. {
    10.     public Vector3 centre;
    11.     public float radius = 5f;
    12.     public List<GameObject> objects = new List<GameObject> ();
    13.     public Dictionary<int, Vector3> verts = new Dictionary<int, Vector3> ();
    14.     private Transform target;
    15.     private Visah v;
    16.     private LineRenderer line;
    17.     private MeshCollider meshCollider;
    18.     public ExpandInDirection (Button b, ControlType c): base(b, c){}
    19.  
    20.     public override IEnumerator Execute ()
    21.     {
    22.         v = GameObject.FindObjectOfType<Visah> ();
    23.         if (v != null)
    24.         {
    25.             line = v.GetComponent<LineRenderer> ();
    26.             meshCollider = v.GetComponent<MeshCollider> ();
    27.         }
    28.  
    29.         while (isActive)
    30.         {
    31.             RaycastHit hit;
    32.             if (Physics.Raycast (Camera.main.ScreenPointToRay (Input.mousePosition), out hit))
    33.             {
    34.                
    35.                 if (meshCollider.sharedMesh != null || meshCollider != null) {
    36.                     Mesh m = meshCollider.sharedMesh;
    37.                     int[] tris = m.triangles;
    38.                     Vector3 p0 = m.vertices [tris [hit.triangleIndex * 3 + 0]];
    39.                     Vector3 p1 = m.vertices [tris [hit.triangleIndex * 3 + 1]];
    40.                     Vector3 p2 = m.vertices [tris [hit.triangleIndex * 3 + 2]];
    41.  
    42.                     verts.Clear ();
    43.                     verts.Add (0, p0);
    44.                     verts.Add (1, p1);
    45.                     verts.Add (2, p2);
    46.                     line.SetPosition (0,p0);
    47.                     line.SetPosition (1,p1);
    48.                     line.SetPosition (2,p2);
    49.                     line.SetPosition (3,p0);
    50.                 }
    51.                 if (Input.GetMouseButtonDown (0))
    52.                 {
    53.                     objects.Clear ();
    54.                     for (int k = 0; k < verts.Count; k++)
    55.                     {
    56.                         objects = v.allObjects.Where (item => item.GetComponent<MeshFilter> ().mesh.vertices.Contains (verts [k])).ToList ();
    57.                         v.currentObjects = objects;
    58.                         Debug.Log ("objects: " + objects.Count);
    59.                     }
    60.                 }
    61.                 yield return null;//new WaitForSeconds(0.1f);
    62.             }
    63.         }
    64.     }
    65.  
    66.     public override void Stop()
    67.     {
    68.         line.SetPositions(new Vector3[] {Vector3.zero,Vector3.zero,Vector3.zero,Vector3.zero});
    69.         //v.currentObjects = v.allObjects;
    70.         base.Stop ();
    71.     }
    72. }
    73.  
    any idea as to how or where to begin debugging to find the freeze point?
    all seems good in the profiler, drawcalls or fps...
     
  2. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    freeze as in unity locks up and you have to close via task manager? or is the editor still responding enough so you can stop the runtime?

    (first case generally indicates infinite loop)
     
  3. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,749
    first case :-(
    infinite loop at random times? the freeze feels like an infinite loop but how and where does it come from at different points in runtime?
     
  4. CrymX

    CrymX

    Joined:
    Feb 16, 2015
    Posts:
    179
    The only infinite loop i see is that

    Are you sure this raycast can return false ?
     
    Last edited: Sep 14, 2016
    jister likes this.
  5. Dave-Carlile

    Dave-Carlile

    Joined:
    Sep 16, 2012
    Posts:
    967
    In the second listing, your yield return null is inside of the Raycast if statement. So if that raycast ever fails you'll enter an infinite loop.
     
    CrymX likes this.
  6. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,749
    yes, it's checking if there is any other mesh in it's grow path, the moment the raycast doesn't hit anything it proceeds.

    hmm don't see it inside the cast? it's inside the while as i see it?
    edit,edit: aha no in here it's in the cast.. as i wrote here below, i deleted some commented text to paste the code here, must have been this that caused my app to crash the moment i activated the tool. anyway undo a couple of times and cleaning up the script seemed to have removed the freeze...

    edit:
    hmm deleted some commented text, got a new crash, probably deleted a line to many orso, undo,undo,undo,... until i couldn't anymore and it magically seems to be gone... !! I hate it when that happens because now i can't figure out what caused/solved it!!!
    i was monitoring the task manager while running the game and strange thing is that the memory can climb up quite high to 7-900 ish and the without any actions drops all of a sudden to 1-200 ish and starts climbing again, while my draw calls and other things in the stats stay the same, actually only thing climbing is the vertex count?
    any idea what that's about?
    i don't clear anything with that long an interval between. i clear most lists and so every cycle...?
     
  7. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,749
    darn it, i go back to unity where the app was still running while posting here, i use the expand in direction tool once again... and freeze x-(
    memory in task manager indicated 239mb... so i guess it's not a memory issue
    i would notice an infinite loop by memory usage right?
    any other ideas?
     
  8. Dave-Carlile

    Dave-Carlile

    Joined:
    Sep 16, 2012
    Posts:
    967
    If Unity is completely unresponsive you're most likely dealing with an infinite loop. Look at every while loop you have and make sure that every path provides an exit condition and/or there is a yield in every execution path if you're dealing with a Coroutine.

    Here is your second listing with much of the code removed, which shows that the yield is inside the Raycast check.

    Code (csharp):
    1.   public override IEnumerator Execute ()
    2.     {
    3.         // snip
    4.  
    5.         while (isActive)
    6.         {
    7.             if (Physics.Raycast (Camera.main.ScreenPointToRay (Input.mousePosition), out hit))
    8.             {
    9.                 if (meshCollider.sharedMesh != null || meshCollider != null) {
    10.                   // snip
    11.                 }
    12.                
    13.                 if (Input.GetMouseButtonDown (0))
    14.                 {
    15.                   // snip
    16.                 }
    17.                
    18.                 // this is inside the if
    19.                 yield return null;//new WaitForSeconds(0.1f);
    20.             }
    21.         }
    22.     }
    Since the Rayast can return false, this leaves a possible code path that looks like this...

    Code (csharp):
    1. while (isActive)
    2. {
    3. }
    4.  
    Coroutines don't run in parallel - they are a for of cooperative multitasking. They must yield execution periodically or nothing else can run. If you're never yielding then nothing else will ever run, including the Unity editor.

    You need to go through any other loop you have and make sure there is an exit for the loop or you're always calling yield.
     
    Kiwasi likes this.
  9. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,749
    in the first script i call CombineMesh() after the while loop in the Grow Enumerator.
    the CombineMesh() has two while loops:
    Code (CSharp):
    1.  while (i < allObjects.Count) {
    2.             combine[i].mesh = allObjects[i].GetComponent<MeshFilter>().sharedMesh;
    3.             combine[i].transform = allObjects[i].transform.localToWorldMatrix;
    4.             allObjects[i].gameObject.SetActive(false);
    5.             i++;
    6.         }
    and
    Code (CSharp):
    1.  while(Physics.Raycast (Vector.GetCentroid(mesh.vertices), mesh.normals [0], 2f))
    2.         {
    3.             next = Random.Range (0, currentObjects.Count);
    4.             mesh = currentObjects [next].GetComponent<MeshFilter> ().sharedMesh;
    5.         }
    as far as i know they don't need a yield, all the other while loops in the coroutines have a yield.
    Code (CSharp):
    1. IEnumerator Grow()
    2.     {
    3.         float count = growTime;
    4.         while (count > 0)
    5.         {
    6.             Debug.DrawRay (v, growDirection * 4f);
    7.  
    8.             v+=growDirection*Time.deltaTime;
    9.             count -= growRate;
    10.             Builder.RecalculateTriangles (allObjects, v);
    11.             yield return new WaitForSeconds (growRate);
    12.         }
    13.         CombineMeshes ();
    14.     }
    Code (CSharp):
    1.     public override IEnumerator Execute ()
    2.     {
    3.        
    4.         v = GameObject.FindObjectOfType<Visah> ();
    5.         if (v != null) {
    6.             line = v.GetComponent<LineRenderer> ();
    7.             meshCollider = v.GetComponent<MeshCollider> ();
    8.         }
    9.  
    10.         while (isActive)
    11.         {
    12.             RaycastHit hit;
    13.             if (Physics.Raycast (Camera.main.ScreenPointToRay (Input.mousePosition), out hit))
    14.             {
    15.                
    16.                 if (meshCollider.sharedMesh != null || meshCollider != null) {
    17.                     Mesh m = meshCollider.sharedMesh;
    18.                     int[] tris = m.triangles;
    19.                     Vector3 p0 = m.vertices [tris [hit.triangleIndex * 3 + 0]];
    20.                     Vector3 p1 = m.vertices [tris [hit.triangleIndex * 3 + 1]];
    21.                     Vector3 p2 = m.vertices [tris [hit.triangleIndex * 3 + 2]];
    22.                     verts.Clear ();
    23.                     verts.Add (0, p0);
    24.                     verts.Add (1, p1);
    25.                     verts.Add (2, p2);
    26.                     line.SetPosition (0,p0);
    27.                     line.SetPosition (1,p1);
    28.                     line.SetPosition (2,p2);
    29.                     line.SetPosition (3,p0);
    30.                 }
    31.                 if (Input.GetMouseButtonDown (0)) {
    32.                     objects.Clear ();
    33.                     for (int k = 0; k < verts.Count; k++) {
    34.                         objects = v.allObjects.Where (item => item.GetComponent<MeshFilter> ().mesh.vertices.Contains (verts[k])).ToList();
    35.                     }
    36.                     v.currentObjects = objects;
    37.                     Debug.Log ("objects: " + objects.Count);
    38.                 }
    39.             }
    40.             yield return null;//new WaitForSeconds(0.1f);
    41.         }
    42.     }
    43.  
    even the virtual one in the control base class
    Code (CSharp):
    1. public virtual IEnumerator Execute ()
    2.     {
    3.         yield return null;
    4.     }
     
  10. Dave-Carlile

    Dave-Carlile

    Joined:
    Sep 16, 2012
    Posts:
    967
    Your second listing can cause an infinite loop if Raycast returns true every time. Relying on something like that as a loop control is dangerous.

    Otherwise, time to fire up the debugger or add log messages or remove code until it goes away, and so on using various other debugging techniques. From the symptoms you've described the most likely cause seems to be an infinite loop somewhere.
     
    jister likes this.
  11. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,749
    i guess it was that one then, because after commenting it out I could go on until i ran out off memory :)
    i changed it to this for now,
    Code (CSharp):
    1. while(Physics.Raycast (Vector.GetCentroid(mesh.vertices), mesh.normals [0], 2f) && i < currentObjects.Count)
    2.         {
    3.             next = Random.Range (0, currentObjects.Count);
    4.             mesh = currentObjects [next].GetComponent<MeshFilter> ().sharedMesh;
    5.             i++;
    6.             Debug.Log ("intercepting: "+i);
    7.         }
    @CrymX i should have looked better when you first said it. @Dave-Carlile thanks for spotting it for me
     
    Dave-Carlile likes this.