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

Question Trying to lock a value for a specified time (Is My While loop infinite?)

Discussion in 'Scripting' started by BenevolenceGames, Aug 31, 2022.

  1. BenevolenceGames

    BenevolenceGames

    Joined:
    Feb 17, 2021
    Posts:
    128
    When trying to enter Play Mode after adding the following script, I am stuck at the entering.Playmode loading bar. I think it's getting into an infinite loop, but for the life of me I cant see how. I figured I'd ask some more talented minds to take a peek. Thanks guys.


    The Suspected Problem
    Code (CSharp):
    1.     public IEnumerator LockGridValueForSeconds(Vector3 worldPosition, int duration)
    2.     {
    3.         Debug.Log("Running");
    4.         int i = 0;
    5.         int value = grid.GetValue(worldPosition);
    6.         float time = Time.time;
    7.         while (Time.time <= time + duration)
    8.         {
    9.             i++;
    10.             Debug.Log("This is scary");
    11.             if (i > 10)
    12.             {
    13.                 Debug.Log("Firing failsafe!");
    14.                 break;
    15.             }
    16.         }
    17.         Debug.Log("Nothing happening");
    18.         yield return null;
    19.  
    20.     }
    The Whole Script
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Testing : MonoBehaviour
    6. {
    7.     [SerializeField] private HeatmapVisual heatmapVisual;
    8.     private Grid grid;
    9.     private void Start()
    10.     {
    11.  
    12.         grid = new Grid(25, 25, 1, Vector3.zero, heatmapVisual.HEAT_MAP_MIN_VALUE, heatmapVisual.HEAT_MAP_MAX_VALUE);
    13.  
    14.         heatmapVisual.SetGrid(grid);
    15.     }
    16.  
    17.     private void Update()
    18.     {
    19.         //if (Input.GetMouseButtonDown(0))
    20.         //{
    21.         //    Vector3 mouseWorldPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    22.         //    mouseWorldPosition.z = 0;
    23.         //    int value = grid.GetValue(mouseWorldPosition);
    24.         //    grid.AddValue(mouseWorldPosition, 100, 5, 40);
    25.         //}
    26.  
    27.         Vector3 mouseWorldPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    28.         mouseWorldPosition.z = 0;
    29.         int value = grid.GetValue(mouseWorldPosition);
    30.         grid.AddValue(mouseWorldPosition, 5, 2, 10);
    31.         StartCoroutine(LockGridValueForSeconds(mouseWorldPosition, 1));
    32.  
    33.     }
    34.  
    35.     public IEnumerator LockGridValueForSeconds(Vector3 worldPosition, int duration)
    36.     {
    37.         Debug.Log("Running");
    38.         int i = 0;
    39.         int value = grid.GetValue(worldPosition);
    40.         float time = Time.time;
    41.         while (Time.time <= time + duration)
    42.         {
    43.             i++;
    44.             Debug.Log("This is scary");
    45.             if (i > 10)
    46.             {
    47.                 Debug.Log("Firing failsafe!");
    48.                 break;
    49.             }
    50.         }
    51.         Debug.Log("Nothing happening");
    52.         yield return null;
    53.  
    54.     }
    55.  
    56. }
    57.  
    The Grid Class
    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using TMPro;
    4.  
    5. public class Grid
    6. {
    7.     public event EventHandler<OnGridValueChangedEventArgs> OnGridValueChanged;
    8.     public class OnGridValueChangedEventArgs : EventArgs
    9.     {
    10.         public int x;
    11.         public int y;
    12.     }
    13.  
    14.     private Vector3 originPosition;
    15.     private int width;
    16.     private int height;
    17.     private float cellSize;
    18.     private int minValue;
    19.     private int maxValue;
    20.  
    21.     private int[,] gridArray;
    22.     private TextMeshPro[,] debugTextArray;
    23.  
    24.     public Grid(int width, int height, float cellSize, Vector3 originPosition, int minValue, int maxValue)
    25.     {
    26.         this.width = width;
    27.         this.height = height;
    28.         this.cellSize = cellSize;
    29.         this.originPosition = originPosition;
    30.         this.minValue = minValue;
    31.         this.maxValue = maxValue;
    32.  
    33.         gridArray = new int[width, height];
    34.  
    35.         bool showDebug = true;
    36.         if (showDebug)
    37.         {
    38.             debugTextArray = new TextMeshPro[width, height];
    39.  
    40.             for (int x = 0; x < gridArray.GetLength(0); x++)
    41.             {
    42.                 for (int y = 0; y < gridArray.GetLength(1); y++)
    43.                 {
    44.                     debugTextArray[x, y] = CreateWorldText(gridArray[x, y].ToString(), null, GetWorldPosition(x, y) + new Vector3(cellSize * .5f, cellSize * .5f), Color.white, 3, x + " / " + y);
    45.  
    46.                     Debug.DrawLine(GetWorldPosition(x, y), GetWorldPosition(x, y + 1), Color.white, 100);
    47.                     Debug.DrawLine(GetWorldPosition(x, y), GetWorldPosition(x + 1, y), Color.white, 100);
    48.                 }
    49.             }
    50.             Debug.DrawLine(GetWorldPosition(0, height), GetWorldPosition(width, height), Color.white, 100);
    51.             Debug.DrawLine(GetWorldPosition(width, 0), GetWorldPosition(width, height), Color.white, 100);
    52.  
    53.             OnGridValueChanged += (object sender, OnGridValueChangedEventArgs eventArgs) =>
    54.             {
    55.                 debugTextArray[eventArgs.x, eventArgs.y].text = gridArray[eventArgs.x, eventArgs.y].ToString();
    56.             };
    57.         }
    58.     }
    59.  
    60.     private TextMeshPro CreateWorldText(string text, Transform parent, Vector3 position, Color color, float fontSize, string nameModifier)
    61.     {
    62.         GameObject worldText = new GameObject("Cell" + nameModifier, typeof(TextMeshPro));
    63.         TextMeshPro textMeshPro = worldText.GetComponent<TextMeshPro>();
    64.         textMeshPro.text = text;
    65.         textMeshPro.gameObject.transform.parent = parent;
    66.         textMeshPro.gameObject.transform.localPosition = position;
    67.         textMeshPro.color = color;
    68.         textMeshPro.fontSize = fontSize;
    69.         textMeshPro.alignment = TextAlignmentOptions.Center;
    70.         return textMeshPro;
    71.     }
    72.  
    73.     public float GetCellSize()
    74.     {
    75.         return cellSize;
    76.     }
    77.  
    78.     public Vector3 GetWorldPosition(int x, int y)
    79.     {
    80.         return new Vector3(x, y) * cellSize + originPosition;
    81.     }
    82.  
    83.     public void GetXY(Vector3 worldPosition, out int x, out int y)
    84.     {
    85.         x = Mathf.FloorToInt((worldPosition.x - originPosition.x) / cellSize);
    86.         y = Mathf.FloorToInt((worldPosition.y - originPosition.y) / cellSize);
    87.     }
    88.  
    89.     public void SetValue(int x, int y, int value)
    90.     {
    91.         if (x >= 0 && y >= 0 && x < width && y < height)
    92.         {
    93.             gridArray[x, y] = Mathf.Clamp(value, minValue, maxValue);
    94.             if (OnGridValueChanged != null) OnGridValueChanged(this, new OnGridValueChangedEventArgs { x = x, y = y });
    95.             debugTextArray[x, y].text = gridArray[x, y].ToString();
    96.         }
    97.     }
    98.  
    99.     public void SetValue(Vector3 worldPosition, int value)
    100.     {
    101.         int x, y;
    102.         GetXY(worldPosition,out x,out y);
    103.         SetValue(x, y, value);
    104.     }
    105.     public void AddValue(int x, int y, int value)
    106.     {
    107.         SetValue(x, y, GetValue(x, y) + value);
    108.     }
    109.  
    110.     public int GetValue(int x, int y)
    111.     {
    112.         if (x >= 0 && y >= 0 && x < width && y < height)
    113.         {
    114.             return gridArray[x, y];
    115.         }
    116.         else
    117.         {
    118.             return 0;
    119.         }
    120.  
    121.     }
    122.  
    123.     public int GetValue(Vector3 worldPosition)
    124.     {
    125.         int x, y;
    126.         GetXY(worldPosition, out x, out y);
    127.         return GetValue(x, y);
    128.     }
    129.  
    130.     public int GetWidth()
    131.     {
    132.         return width;
    133.     }
    134.  
    135.     public int GetHeight()
    136.     {
    137.         return height;
    138.     }
    139.  
    140.     public void AddValue(Vector3 worldPosition, int value, int fullValueRange, int totalRange)
    141.     {
    142.         int lowerValueAmount = Mathf.RoundToInt((float)value / (totalRange - fullValueRange));
    143.  
    144.  
    145.         GetXY(worldPosition, out int originX, out int originY);
    146.         for (int x = 0; x < totalRange; x++)
    147.         {
    148.             for (int y = 0; y < totalRange - x; y++)
    149.             {
    150.                 int radius = x + y;
    151.                 int addValueAmount = value;
    152.                 if (radius > fullValueRange)
    153.                 {
    154.                     addValueAmount -= lowerValueAmount;
    155.                 }
    156.  
    157.                 AddValue(originX + x, originY + y, addValueAmount);
    158.                 if (x != 0)
    159.                 {
    160.                     AddValue(originX - x, originY + y, addValueAmount);
    161.                 }
    162.  
    163.                 if (y != 0)
    164.                 {
    165.                     AddValue(originX + x, originY - y, addValueAmount);
    166.                     if(x != 0)
    167.                     {
    168.                         AddValue(originX - x, originY - y, addValueAmount);
    169.                     }
    170.                 }
    171.             }
    172.         }
    173.     }
    174. }
     
  2. pixaware_pwedrowski

    pixaware_pwedrowski

    Joined:
    Oct 25, 2018
    Posts:
    116
    Are you sure you want to trigger
    LockGridValueForSeconds
    coroutine every frame?

    Also this:
    Code (CSharp):
    1. float time = Time.time;
    2. while (Time.time <= time + duration)
    Can be simplified into
    yield return new WaitForSecondsRealtime(timeInSeconds);
     
  3. BenevolenceGames

    BenevolenceGames

    Joined:
    Feb 17, 2021
    Posts:
    128

    Essentially I have a heatmap and when you hover the mouse over a grid cell, it begins incrementing the value. I want to be able to lock the value for a specified time after it's been incremented so that it slows the process down of reaching max value.
     
  4. BenevolenceGames

    BenevolenceGames

    Joined:
    Feb 17, 2021
    Posts:
    128
    I do have an event that triggers when the value of a cell has changed, I suppose I should subscribe a void to trigger the coroutine from instead of running it every frame.
     
  5. pixaware_pwedrowski

    pixaware_pwedrowski

    Joined:
    Oct 25, 2018
    Posts:
    116
    Alternatively, you can move lock logic to cells instead of keeping it in a separate manager. There you can make a flag, say
    isCellLocked
    if false and it reached max value, run a coroutine that will switch the flag and release it after x seconds
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,762
    Unity Locks Up 100% Solid While Your Script Code Is Running

    If you want anything about Unity to change, you must either:

    -
    return
    from a method
    -
    yield
    from a coroutine.

    There are NO EXCEPTIONS in scripting land.

    Your while() loop above will LOCK, and
    Time.time
    will never change.