Coroutine making unity freeze

I know this is from the coroutine but I don’t know how to fix it.
Video showing the problem
Here’s my script:

#pragma strict

var RN : int = -1;
var groundPart : GameObject[];
var destroyCooldown : float = 5;
var redTime : float = 0.5;
var groundCount : int = 225;

function Start () {
groundPart = GameObject.FindGameObjectsWithTag("Ground");
groundCount = groundPart.Length;
StartCoroutine("DestroyGround");
}

function FixedUpdate () {
if(groundPart.Length <= 0 || groundCount <= 0){
StopCoroutine("DestroyGround");
}
}

function DestroyGround () {
while(true) {
RN = Random.Range(0, groundPart.length);
if(RN <= groundPart.length && groundPart[RN]) { groundPart[RN].GetComponent(MeshRenderer).material.color = Color.red;
yield WaitForSeconds(redTime);
groundPart[RN] = null;
//groundPart.Length -= 1; //might be the solution ?
yield WaitForSeconds(destroyCooldown);
RN = -1;
groundCount -= 1;
}
}
}

Thnaks for ur help.

A coroutine is a “cooperative” method. When you aren’t cooperative inside of it it’s your problem ^^. To be cooperative you have to make sure to call yield. First have a look at your method formatted in a way it makes sense:

function DestroyGround ()
{
    while(true)
    {
        RN = Random.Range(0, groundPart.length);
        if(RN <= groundPart.length && groundPart[RN])
        {
            groundPart[RN].GetComponent(MeshRenderer).material.color = Color.red;
            yield WaitForSeconds(redTime);
            groundPart[RN] = null;
            //groundPart.Length -= 1; //might be the solution ?
            yield WaitForSeconds(destroyCooldown);
            RN = -1;
            groundCount -= 1;
        }
    }
}

Here you can clearly see that all your yield statements are inside your “if” body. That means in the case where that if never turns true, your method essentially becomes:

function DestroyGround ()
{
    while(true)
    {
        RN = Random.Range(0, groundPart.length);
    }
}

As you can see when the if statement is not executed you are caught in an infinite loop without ever handing the control back to the system which results in a freeze.

So what are the possible reasons for the condition to become true. Your first condition is that RN is smaller or equal to “groundPart.length” (which btw makes no sense. It can’t be equal, that would throw an out of bounds exception).

Since RN is Random.Range(0, groundPart.length); it will always be in the range

0 <= RN < groundPart.length

So as long as your array is not empty the first condition doesn’t give you any problems, even it’s not necessary / useless.

The second condition is the important one: groundPart[RN]
You check if the element you’re currently checking is not null. Since everytime you actually pick an element and you’re entering the if statement you’re setting the element to null. That means you eventually use up all elements in the array so all elements become null. In this case you will never enter the if statement ever again which will cause an infinite loop

If this

if(RN <= groundPart.length && groundPart[RN])

will return false then while(true) will loop to infinity in one frame, never letting it end.
Add there something to let it go, or will break while loop, i.e.

while(true)
{
    RN = Random.Range(0, groundPart.length);
    if(RN <= groundPart.length && groundPart[RN]) {
    ...
    }
    yield return new WaitForEndOfFrame();
}