Home > other >  Unity crashes after random if statement
Unity crashes after random if statement

Time:07-30

I am trying to make some code that randomises my unity game's levels. This method is supposed to make a square filled with enemies. The IsPowered boolean randomly decides if a cloumn should be moving verticaly or not:

void Square(GameObject ship, float dY, float dX, float h, float w)
    {
        int i, j;
        bool IsPowered = false;
        float X = 2   Camera.transform.position.x, speed = Random.Range(50.0f, 100.0f);

        //set position
        float Y = h / 2 * dY   dY / 2;
        for (j = 1; j <= w; j  )
        {
            IsPowered = false;
            if(Random.Range(0, 1) == 1)
                IsPowered = true;

            for (i = 1; i <= h; i  )
            {
                //makes ship
                temp = Instantiate(ship);
                if(IsPowered)
                {
                    if(Random.Range(0, 1) == 1)
                        speed = -speed;
                    temp.GetComponent<Rigidbody2D>().AddForce(new Vector2(0, speed));
                }
                temp.transform.position = new Vector3(X   j * dX, Y - i * dY, 0);
            }
        }
    }

The problem is that if the first Random.Range(0, 1) statement is true unity freezes. Btw I checked and if I remove the statment or make is always be true this doesn't happen. Square being called:

void LateUpdate()
    {
        //if the player has moved 2 tiles then strat  a fight
        curentX = Camera.transform.position.x;
        if(Mathf.Abs(lastX - curentX) >= 10 && Mathf.Abs(curentX - 60) >= 8)
        {
            lastX = curentX;
            InBattle = true;
            //!Arguments: 0 - square, 1 - triangle, 2 - circle, 3 - bounce;
            CallRandom(0);
        }

        //if player has defeated all enemies exits battle mode
        EnemiesOnBoard = GameObject.FindWithTag("Enemy");
        if(EnemiesOnBoard == null && InBattle)
        {
            InBattle = false;
        }
    }

CallRandom method:

   void CallRandom(float nb)
    {
        float dY, h, dX, w;
        int nb2;
        switch (nb)
        {
            //sets up random stuff for square type of formation
            case 0:
                //randomises vertical stuff
                dY = Random.Range(1.0f, 2.0f);
                h = Random.Range(2, 4);
                while(h / 2 * dY   dY / 2 >= 4)
                    dY -= 0.1f;

                //randomizez horizontal stuff
                dX = Random.Range(1.0f, 2.0f);
                w = Random.Range(2, 4);
                while(w * dX > 5);
                    dX -= 0.1f;
                
                Square(EType0, dY, dX, h, w);
                break;
            //makes random triagnle type formation
            case 1:
                //vertical
                dY = Random.Range(1.0f, 2.0f);
                h = Random.Range(2.0f, 5.0f);
                while(h / 2 * dY   dY / 2  >= 4)
                    dY -= 0.1f;

                //horizontal
                dX = Random.Range(1.0f, 3.0f);
                while(dX * h >= 5)
                    dX -= 0.1f;

                Triangle(EType0, dY, dX, h);
                break;
            //makes random circle type fromation
            case 2:
                nb2 = Random.Range(4, 9);
                Circle(EType0, nb2);
                break;
            //makes random bouncie formation
            case 3:
                nb2 = Random.Range(5, 12);
                Bounce(EType0, nb2);
                break;
            default: 
                print("Something aint right");
                break;
        }
    }

EDIT: I did some more testing and the problem seems to originate from one or both of the while loop in case 0 of the CallRandom method and it doesn't seem to happen enywhere else. Still don't know why is doesn't work

EDIT: I finally found the problem, and I actually hate myself now. The second while loop in case 0 of CallRandom had a ";" at the end of it so it created an infinite loop!

CodePudding user response:

The problem with your code is that there appears to be a direct link with frame updating (specifically LateUpdate()) and spawning new pre-fabs attached to new GameObjects. Our focus here isn't so much the prefabs but rather the GameObjects. GameObjects are a kinda expensive and there appears to be an upper limit you can have at one time per scene.[1][2]

Now LateUpdate is called every frame and let's say your game is running at 60 frames/second (FPS). So worst case is that you might be spawning 60 GameObjects/second. Unless you have coded some sort of lifetime management, you might be reaching Unity's limit causing it to crash.

Thar be dragons

It's actually a little worse. LateUpdate() (remember 60 FPS in our example) calls CallRandom() which calls Square() which living up to it's name isn't limited to spawning a single GameObject but a square of them with your nested loops of w * h. Backtracking to CallRandom() we see that w and h could be anything up to 4 in value.

So:

<frame-rate> x 4 x 4 = <spawn-rate>

...or: 

60 x 4 x 4 = 960 game objects/sec

With some reports of the upper limit of GameObjects to be ~5,000, you would exceed that in approximately 5.2 seconds! [1][2]

The fix

You have a few choices:

  1. if you plan on spawning say 960 objects/sec you will need to delete older objects as you go. Think of the famous Snake game

  2. consider restructuring your visuals so that you need less GameObjects. e.g. Unity's Particle System works by having a single GameObject and component yet it can render 1,000s of particles effortlessly


1 https://answers.unity.com/questions/408298/max-number-of-gameobjects-5000-1.html

2 https://answers.unity.com/questions/365552/why-would-you-use-a-scriptable-object-versus-an-em.html

  • Related