Script freezes unity whenever a specific function is wrong.,My Script freezes whenever I try to use a function I made called "ChangeYeild()"

I am having a problem whenever I attempt to run a new Script I made, the script is for drawing a catan board. Here is what the code is supposed to do:

  1. Draw a Catan Board of a given Size
  2. Have an array of the Catan Board that was made to the size needed
  3. Change components of the GameObjects as listed: (The Yeild type, Mesh based off that Yeild type, and Draw number/yeild)

The actual code needs to also be able to dynamically change the amount of tiles based on size but I will work on that later.

Whenever I run this script, nothing happens and Unity freezes. After doing some tests I know for a fact that the only problematic function is ChangeYeild, everything else works as intended. Does anybody know how to fix this?

Here is my code -

using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using UnityEngine;
using static UnityEngine.Rendering.DebugUI;
using Random = UnityEngine.Random;

public class Playboard : MonoBehaviour
{
    public int boardsize = 2;
    int TileNumber = 1;
    int fullsizeofarray = 0;
    int currentlocationinarrayforbuilding = 0;

    public GameObject[] TestTile = new GameObject[0];

    public GameObject OriginalTile;

    // Start is called before the first frame update
    void Start()
    {
        Debug.Log($"Running Tile Yeild Caculations");
    }

    // Update is called once per frame
    void Update()
    {
        BuildBoard();
    }

    //Functions for building the first board

    void BuildBoard()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Debug.Log($"Started the creation of the array");
            CreateRows(boardsize);
            CreateFinalRow(boardsize);
            CreateRows(boardsize);

            InstantiateRows(1f, boardsize);
            InstantiateFinalRow(boardsize);
            InstantiateRows(-1f, boardsize);

            ChangeYeild();
        }
    }

    void InstantiateRows(float NegativeValue, int size)
    {
        float zlocalation = 1f;

        for (int i = 0; i < size; i++)
        {
            //this determines weather it is a down piece of an up piece
            if (zlocalation == 1f)
            {
                zlocalation = 0f;
            }
            else if (zlocalation == 0f)
            {
                zlocalation = 1f;
            }

            // determines the number of times we need to make a new tile
            //per a given row
            int rowlength = i + 2;

            // Temp value representing the position we are in in the
            //drawing of the board.
            int n = (size/2) * -1;   

            //Determining it's location on the X axis
            float DistanceFromCenter;

            DistanceFromCenter = ((size - i) * 1.5f) * NegativeValue;

            //Larger Board Location Adjustment

            int LBA;

            if(IsEven(i))
                {
                LBA = i / 2;
                }
            else
            {
                LBA = (i - 1) / 2;
            }


            for (int r = n; r < rowlength; r++)
            {
                float fp = n * 2;

                TestTile[currentlocationinarrayforbuilding] = OriginalTile;

                var NewTile = Instantiate(TestTile[currentlocationinarrayforbuilding], new Vector3(DistanceFromCenter, 0, fp + (LBA * -2) - zlocalation), transform.rotation);
                NewTile.name = $"Tile.{TileNumber}";
                TestTile[currentlocationinarrayforbuilding] = NewTile;
                TileNumber++;
                n++;
                currentlocationinarrayforbuilding++;
                Debug.Log($"Spawned in Tile {NewTile.name}");
            }
        }
    }

    void InstantiateFinalRow(int size)
    {
        float zlocalation;

        if (IsEven(size))
        {
            zlocalation = 0f;
        }
        else
        {
            zlocalation = 1f;
        }

        int rowlength = size + 1;

        //Larger Board Location Adjustment

        int LBA;

        if (IsEven(size))
        {
            LBA = (size / 2) -1;
        }
        else
        {
            LBA = ((size + 1) / 2) - 1;
        }

        rowlength -= LBA;

        // Temp value representing the position we are in in the
        //drawing of the board.
        int n = (size * -1);

        for (int r = n; r < rowlength; r++)
        {
            float fp = n * 2;

            TestTile[currentlocationinarrayforbuilding] = OriginalTile;

            var NewTile = Instantiate(TestTile[currentlocationinarrayforbuilding], new Vector3(0, 0, fp + zlocalation), transform.rotation);
            NewTile.name = $"Tile.{TileNumber}";
            TestTile[currentlocationinarrayforbuilding] = NewTile;
            TileNumber++;
            n++;
            currentlocationinarrayforbuilding++;
            Debug.Log($"Spawned in Tile {NewTile.name}");
        }
    }

    public static bool IsEven(int intValue)
    {
        return ((intValue & 1) == 0);
    }

    void CreateRows(int size)
    {
        for (int i = 0; i < size; i++)
        {

            // determines the number of times we need to make a new tile
            //per a given row
            int rowlength = i + 2;

            // Temp value representing the position we are in in the
            //drawing of the board.
            int n = (size / 2) * -1;


            for (int r = n; r < rowlength; r++)
            {
                fullsizeofarray++;

                Array.Resize<GameObject>(ref TestTile, fullsizeofarray);

                Debug.Log($"Created in Tile {fullsizeofarray}");
            }
        }
    }

    void CreateFinalRow(int size)
    {
        int rowlength = size + 1;

        //Larger Board Location Adjustment

        int LBA;

        if (IsEven(size))
        {
            LBA = (size / 2) - 1;
        }
        else
        {
            LBA = ((size + 1) / 2) - 1;
        }

        rowlength -= LBA;

        // Temp value representing the position we are in in the
        //drawing of the board.
        int n = (size * -1);

        for (int r = n; r < rowlength; r++)
        {
            fullsizeofarray++;

            Array.Resize<GameObject>(ref TestTile, fullsizeofarray);
            Debug.Log($"Created in Tile {fullsizeofarray}");
        }
    }

    void ChangeYeild()
    {
        Debug.Log($"Started the Yeild Script");
        //Values for Desert Tiles
        bool Desertedtile = false;
        bool Deserttilechanged = false;
        int deserttilechange = TestTile.Length;

        //Finding the ammount for everything else

        int amountoftilesexcludingdesert = TestTile.Length - 1;

        int AmountofMountains = 3;
        int AmountofBogs = 3;
        int AmountofForest = 4;
        int AmountofFeild = 4;
        int AmountofPaster = 4;

        // Change the yeilds for each tile that had been spawned
        for (int i = 0; i < TestTile.Length; i++)
        {
            Debug.Log($"Started on Tile{i}");

            bool RoundComplete = false;

            //Checks to see if the Deserted Tile has been spawned, if not, it spawns in the deserted tile
            if (Desertedtile == true)
            {

                Debug.Log($"Testing for Wasteland");

                int DecidingFactor = Random.Range(1, deserttilechange);

                if(DecidingFactor == 1)
                {
                    Debug.Log($"Created Wasteland");

                    bool notoyeild = false;
                    SetYeild(TestTile*, 0, notoyeild);*

TestTile*.name = “Wasteland Tile”;*

Desertedtile = true;
Deserttilechanged = true;
}
else
{
deserttilechange–;
}
}

//Avoids changing the deserted tile to a different tile type
if(Deserttilechanged == false)
{
Debug.Log($“Running Tile Yeild Caculations”);

while (RoundComplete == false)
{
bool yesforcalc = true;

switch ( Random.Range( 1,5 ))
{
case 1:
if(AmountofMountains != 0)
{
SetYeild(TestTile*, 1, yesforcalc);*
RoundComplete = true;
TestTile*.name = $“Mountain Tile {AmountofMountains}”;*
AmountofMountains–;
}
break;

case 2:
if (AmountofBogs != 0)
{
SetYeild(TestTile*, 2, yesforcalc);*
RoundComplete = true;
TestTile*.name = $“Bog Tile {AmountofBogs}”;*
AmountofBogs–;
}
break;

case 3:
if (AmountofForest != 0)
{
SetYeild(TestTile*, 3, yesforcalc);*
RoundComplete = true;
TestTile*.name = $“Forset Tile {AmountofForest}”;*
AmountofForest–;
}
break;

case 4:
if (AmountofFeild != 0)
{
SetYeild(TestTile*, 4, yesforcalc);*
RoundComplete = true;
TestTile*.name = $“Feild Tile {AmountofFeild}”;*
AmountofFeild–;
}
break;

case 5:
if (AmountofPaster != 0)
{
SetYeild(TestTile*, 5, yesforcalc);*
RoundComplete = true;
TestTile*.name = $“Paster Tile {AmountofPaster}”;*
AmountofPaster–;
}
break;

}
}
}
else
{
Deserttilechanged = false;
}
}
}

void SetYeild(GameObject yeildseter, int yeildtype, bool yeildcaculation)
{
Mesh startingmesh;

//changes the Yeild of the object
Tile temptile = yeildseter.GetComponent();
temptile.Type = yeildtype;

//Swaps the mesh of the object
startingmesh = yeildseter.GetComponent().mesh;
temptile.TileMeshes[yeildtype] = yeildseter.GetComponent().mesh;

//Changes the Yeild Value of the Object
if(yeildcaculation)
{
int makesurenot7 = 7;

while (makesurenot7 == 7)
{
temptile.Yeild = Random.Range(2,12);

makesurenot7 = temptile.Yeild;
}

}

}
}
Here is the problematic code alone -

void ChangeYeild()
{
Debug.Log($“Started the Yeild Script”);
//Values for Desert Tiles
bool Desertedtile = false;
bool Deserttilechanged = false;
int deserttilechange = TestTile.Length;

//Finding the ammount for everything else

int amountoftilesexcludingdesert = TestTile.Length - 1;

int AmountofMountains = 3;
int AmountofBogs = 3;
int AmountofForest = 4;
int AmountofFeild = 4;
int AmountofPaster = 4;

// Change the yeilds for each tile that had been spawned
for (int i = 0; i < TestTile.Length; i++)
{
Debug.Log($“Started on Tile{i}”);

bool RoundComplete = false;

//Checks to see if the Deserted Tile has been spawned, if not, it spawns in the deserted tile
if (Desertedtile == true)
{

Debug.Log($“Testing for Wasteland”);

int DecidingFactor = Random.Range(1, deserttilechange);

if(DecidingFactor == 1)
{
Debug.Log($“Created Wasteland”);

bool notoyeild = false;
SetYeild(TestTile*, 0, notoyeild);*

TestTile*.name = “Wasteland Tile”;*

Desertedtile = true;
Deserttilechanged = true;
}
else
{
deserttilechange–;
}
}

//Avoids changing the deserted tile to a different tile type
if(Deserttilechanged == false)
{
Debug.Log($“Running Tile Yeild Caculations”);

while (RoundComplete == false)
{
bool yesforcalc = true;

switch ( Random.Range( 1,5 ))
{
case 1:
if(AmountofMountains != 0)
{
SetYeild(TestTile*, 1, yesforcalc);*
RoundComplete = true;
TestTile*.name = $“Mountain Tile {AmountofMountains}”;*
AmountofMountains–;
}
break;

case 2:
if (AmountofBogs != 0)
{
SetYeild(TestTile*, 2, yesforcalc);*
RoundComplete = true;
TestTile*.name = $“Bog Tile {AmountofBogs}”;*
AmountofBogs–;
}
break;

case 3:
if (AmountofForest != 0)
{
SetYeild(TestTile*, 3, yesforcalc);*
RoundComplete = true;
TestTile*.name = $“Forset Tile {AmountofForest}”;*
AmountofForest–;
}
break;

case 4:
if (AmountofFeild != 0)
{
SetYeild(TestTile*, 4, yesforcalc);*
RoundComplete = true;
TestTile*.name = $“Feild Tile {AmountofFeild}”;*
AmountofFeild–;
}
break;

case 5:
if (AmountofPaster != 0)
{
SetYeild(TestTile*, 5, yesforcalc);*
RoundComplete = true;
TestTile*.name = $“Paster Tile {AmountofPaster}”;*
AmountofPaster–;
}
break;

}
}
}
else
{
Deserttilechanged = false;
}
}
}

Hey there,

please try to post less code next time… The ChangeYield function is all we care for right?

In general when you game freezes the reason is in 99% of cases the usage of a while loop.
In your case that is also the case. Check the following following:

 while (RoundComplete == false)

This will repeat itself unless RoundComplete is true. But it is only true if any Yield was changed.

But now what happens if you create a board that has more tiles to change than there are Mountain/Wood/wheat… tiles to place? It will constantly loop, take a new random number, then check if for example mountains are still available and then repeat the process.

So either you have to extend that loop to check if there are any tiles to place left or (what imo is the way better option) you change that behaviour completely.

If you were to take a list where you add the numbers of your tiles:

List<int> availableTiles = new List<int>();
for(int i=0;i<AmountofMountains;i++) {
      availableTiles.add(1);
}
for(int i=0;i<AmountofBogs ;i++) {
      availableTiles.add(2);
}
//and so on....

then you can simply take this instead of your current logic:

if(availableTiles.Count > 0)
{
        int newTileIndex = Random.Range(0, availableTiles.Count);
        int newTile = availableTiles[newTileIndex];
        availableTiles.RemoveAt(newTileIndex);
        SetYeild(TestTile*, newTile, true);*

}
and that should already replace your complete while loop logic.
(except the setting of the name but for that you simply need a mapping logic or - even better - an enumeration.
public enum TileType {Desert, Mountain, Bog , …}