While loop crashing Unity

Hi guys,

I’m making a tactical rpg and I’m moving the npc with a random function. I use a range between 0 and 4 to set its position.

Initially, i make it inside Start(). At first, the NPC can just move towards or left.

void Start()
    {

        secretNumber = Random.Range(0, 1);
        switch (secretNumber)
        {
            case 0:// NPC moves towards
                targetPosition.y = 1.4f;
                targetPosition.x = this.transform.position.x;
                targetPosition.z = this.transform.position.z - 3;
                break;

            case 1: // npc moves to left
                targetPosition.y = 1.4f;
                targetPosition.z = this.transform.position.z;
                targetPosition.x = this.transform.position.x - 2;
                break;

            default: break;
        }
    }    

Then, I move the npc to targetPosition with this function. I call it in Update(). If the NPC doesn’t find the human player in the grid with its raycasts, he moves:

 void Update()
    {

        if (Physics.Raycast(DetectPlayer.transform.position, DetectPlayer.Left_Right, out DetectPlayer.hitRight) &&
            Physics.Raycast(DetectPlayer.transform.position, -DetectPlayer.Direction, out DetectPlayer.hitFoward) &&
            Physics.Raycast(DetectPlayer.transform.position, -DetectPlayer.Left_Right, out DetectPlayer.hitLeft) &&
            Physics.Raycast(DetectPlayer.transform.position, DetectPlayer.Direction, out DetectPlayer.hitBack))
        {
            if (DetectPlayer.hitRight.transform.tag != "Player" && DetectPlayer.hitFoward.transform.tag != "Player" &&
                DetectPlayer.hitLeft.transform.tag != "Player" && DetectPlayer.hitBack.transform.tag != "Player")
            {
                IsMoving = true;

                if (IsMoving)
                {
                    MoveNPC();
                }
            }
        }

        NewPosition();
    }

I use this function to move the npc:

public void MoveNPC()
    {

        if (secretNumber == 0 && mov.gameManager.NPCTurn)
        {
            this.transform.position = Vector3.MoveTowards(transform.position, targetPosition, velocity * Time.deltaTime);
        }

        if (secretNumber == 1 && mov.gameManager.NPCTurn)
        {
            this.transform.position = Vector3.MoveTowards(transform.position, targetPosition, velocity * Time.deltaTime);
        }

        if (secretNumber == 2 && mov.gameManager.NPCTurn)
        {
            this.transform.position = Vector3.MoveTowards(transform.position, targetPosition, velocity * Time.deltaTime);
        }

        if (secretNumber == 3 && mov.gameManager.NPCTurn)
        {
            this.transform.position = Vector3.MoveTowards(transform.position, targetPosition, velocity * Time.deltaTime);
        }

        if (this.transform.position == targetPosition)
        {
            IsMoving = false;
        }
    }

Then, after the first round, if the NPC still doesn’t detect the human player I use this function NewPosition to set a new position for him. It works, however when the NPC reaches one of the borders of the grid, like in the picture and it’s his turn I need to generate a new number.

So, if his current X is 0 and the number generated is 0 I need to generate a new one, because I that position he can’t move towards anymore. I’ve tried something like this, but it doesn’t work.

if (NPC.gridposition == 0 && secretNumber == 0) {
               NewPosition();
                stucked = true;
  }

How could I do a loop that is executed until he can move? I’m trying to use the Do While statement inside Update() , however the while loop is crashing the program.

Update(){
    if(stucked){
    
    do{ 

           NewPosition();

    }while (stucked = true);
  }
 }

Hi!

Usually when loop is crashing the program that means it repeates constantly without reaching the desired condition, so I gonna assume that in you NewPosition() you did not change stucked variable to false, therefore it got called forever.


However, I would suggest to do couple things for your code to simplify and kinda optimize it without repeating of random function, because meanwhile it will work, but there will be situations where the functions gonna be called 20 times, because random will generate same number as final cell.


What I advise to try:

In your MoveNPC make all other if statements else if when the conditions are mutually exclusive:

     if (secretNumber == 0 && mov.gameManager.NPCTurn)
     {
     }
     else if (secretNumber == 1 && mov.gameManager.NPCTurn)
     {
     }
     else if (secretNumber == 2 && mov.gameManager.NPCTurn)
     {
     }
     else if (secretNumber == 3 && mov.gameManager.NPCTurn)
     {
     }

The thing is that you are checking for secretNumber equality, but when you maintain other if statements separate then even when one of the above already executed the others will get checked for no reason. However, with else if it will ignore any other connected statements if one already executed.


Also I would like to mention your Start() function:

 secretNumber = Random.Range(0, 1);

The thing with Random.Range that it’s EXCLUSIVE with max integer, but INCLUSIVE with max float.

What it means that here you will always have 0 as a random seed, because 1 is exclusive, so you want to change it to:

 secretNumber = Random.Range(0, 2);

Here is a good documentation about it: Unity - Scripting API: Random.Range


So now to your NewPosition() which I cannot see, but I assume that you are simply generating new number for move, so let’s suppose it something like this:

secretNumber = Random.Range(0, 4);

Let’s adjust it so that we will change accordingly to our stuck position case:

secretNumber = Random.Range(0, 4);
while (NPC.gridposition == secretNumber)
{
    secretNumber++;
    secretNumber = secretNumber % 4;
}

So, we are generating random number and then we are checking if gridposition equal to the number as you have done by yourself already. Then we are not re-calculating random but adding +1 to already calculated and make sure it cannot be higher than 3: the % operator is modulus operator, so if the end value will be 3+1 then after modulus it will be 0.

However, you can recalculate if you want and make it this way:

secretNumber = Random.Range(0, 4);
while (NPC.gridposition == secretNumber)
{
    secretNumber = Random.Range(0, 4);
}

That’s up to you.


Let me know if that helps.