Search Unity

  1. If you have experience with import & exporting custom (.unitypackage) packages, please help complete a survey (open until May 15, 2024).
    Dismiss Notice
  2. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice

Function runs fine the first time but crashes if I run it twice?

Discussion in 'Scripting' started by Diesign, Feb 5, 2019.

  1. Diesign

    Diesign

    Joined:
    May 15, 2016
    Posts:
    16
    I have a function that runs fine the first time it executes at start but it crashes the second time I run it after an interaction. I suspect the issue may be related to for-loops creating infinite recursion similar to to the freezing described here but I think my function is just executing once. I also found this but even after 15 minutes nothing executed.

    Here is the function:

    Code (CSharp):
    1.     public void ShuffleCards()
    2.     {
    3.         //Choose Correct Dictionary
    4.         foreach (object key in RandomKey(initialSoundDictQueue).Take(1))
    5.         {
    6.          
    7.             correctSoundDict = key.ToString();
    8.         }
    9.  
    10.  
    11.         //Choose Correct Card
    12.         foreach (object value in RandomValues(cardQueue).Take(1))
    13.         {
    14.             correctCard = (GameObject)value;
    15.             correctCard.AddComponent<CorrectCard>();
    16.         }
    17.  
    18.  
    19.         //Reveal Correct Card
    20.         foreach (object key in RandomKey(initialSoundDictQueue[correctSoundDict]).Take(1))
    21.         {
    22.             string stringKey = key.ToString();
    23.  
    24.             correctObject = initialSoundDictQueue[correctSoundDict][stringKey];
    25.  
    26.             Instantiate(correctObject, correctCard.transform.position, Quaternion.identity, correctCard.transform.GetChild(0));
    27.  
    28.             TextMeshPro title = correctCard.transform.GetChild(1).GetComponent<TextMeshPro>();
    29.  
    30.             string noSpaceTitle = stringKey.Replace(" ", string.Empty);
    31.  
    32.             title.text = noSpaceTitle;
    33.  
    34.             TextMeshPro subhead = correctCard.transform.GetChild(2).GetComponent<TextMeshPro>();
    35.  
    36.             subhead.text = stringKey;
    37.  
    38.         }
    39.     }
    40.  
    41.    public IEnumerable<TValue> RandomValues<TKey, TValue>(IDictionary<TKey, TValue> dict)
    42.     {
    43.         System.Random rand = new System.Random();
    44.         List<TValue> values = Enumerable.ToList(dict.Values);
    45.         int size = dict.Count;
    46.         while (true)
    47.         {
    48.             TValue chosenValue = values[rand.Next(size)];
    49.  
    50.           if (vetList.Contains(chosenValue.ToString()))
    51.             {
    52.                 //print("Contains");
    53.             }
    54.             else
    55.             {
    56.                 vetList.Add(chosenValue.ToString());
    57.                 yield return chosenValue;
    58.             }
    59.         }
    60.     }
    61.  
    62.  
    63.     public IEnumerable<TKey> RandomKey<TKey, TValue>(IDictionary<TKey, TValue> keyQueue)
    64.     {
    65.         System.Random rand = new System.Random();
    66.         List<TKey> Keys = Enumerable.ToList(keyQueue.Keys);
    67.         int size = keyQueue.Count;
    68.         while (true)
    69.         {
    70.             TKey chosenKey = Keys[rand.Next(size)];
    71.  
    72.             if (vetList.Contains(chosenKey.ToString()))
    73.             {
    74.                 print("Contains");
    75.             }
    76.             else
    77.             {
    78.                 vetList.Add(chosenKey.ToString());
    79.                 yield return chosenKey;
    80.             }
    81.         }
    82.     }
    83.  
    84.  
    It runs fine the first time but if I try to run it again to overwrite things I get a hard crash. I don't understand why though. Hope I am not posting this to the wrong place :eek:
     
  2. fire7side

    fire7side

    Joined:
    Oct 15, 2012
    Posts:
    1,819
    One thing you might want to try is StopAllCoroutines before calling it the second time. If you are using some type of counter in there, I don't see one, but if there is, that would need to be reset to 0.
    Other than that, you just have to put debug lines in your code to find out where it is hanging up.
     
  3. doctorpangloss

    doctorpangloss

    Joined:
    Feb 20, 2013
    Posts:
    270
    You can ignore the `StopAllCoroutines` suggestion. You don't use coroutines.

    Your IEnumerator implementations are wrong. You're adding something to `vetList` in 56 to a 1 item large `keyQueue` that causes your RandomKey function to go into an infinite loop. You're way overengineering picking a random item.

    Don't use dictionaries, use lists. You're not quite sure what a key is, based on how you're using them. Just use a list.

    Don't use LINQ to do a random choice. Stop using LINQ altogether, because you're using it wrong in so many ways.
     
  4. SparrowGS

    SparrowGS

    Joined:
    Apr 6, 2017
    Posts:
    2,536
    Totally, why do you need this level of complexity? I didn't follow the code but if it's just random and not some clever behind the scene ordering for some purpose this has no business being this long.
    Why, what's wrong with this?
    It's working perfectly as far as I can tell.
    Code (CSharp):
    1.         public static IEnumerable<T> Randomize<T>(this IEnumerable<T> source) {
    2.            
    3.             System.Random rnd = new System.Random();
    4.             return source.OrderBy<T, int>((item) => rnd.Next());
    5.         }
     
  5. Diesign

    Diesign

    Joined:
    May 15, 2016
    Posts:
    16
    @doctorpangloss The cause of the infinite loop was actually running out of dictionaries. Adding more dictionaries or clearing the vetList before rerunning this function solves the issue.

    Why would I want to use lists in this use case? To my knowledge I can't have a list with nested dictionaries that are ordered by unique strings. Why would you say I am not sure what a key is? I am using it to access information that I am storing in the value. How can I use it more effectively?

    Also curious about LINQ. You say stop using it altogether - why? You also say I am using it wrong in so many ways, would you mind listing them so I can learn instead of just being insulted?
     
    Last edited: Feb 6, 2019
  6. doctorpangloss

    doctorpangloss

    Joined:
    Feb 20, 2013
    Posts:
    270
    Sorry buddy, I didn't mean to be insulting. It just looks like very, very overengineered code that's very hard to read or understand what's going on to normal people.

    Like the words "vetList" and "adding more dictionaries" are sort of meaningless. If you could write, in plain English, what you're trying to accomplish, in the midst of doing that you're going to figure out what's wrong. This is called Rubber duck programming and it will help you a lot more than my giving you tips about how you're using LINQ.

    https://en.wikipedia.org/wiki/Rubber_duck_debugging