Function runs fine the first time but crashes if I run it twice?
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 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:
public void ShuffleCards()
{
print("test");
//Choose Correct Dictionary
foreach (object key in RandomKey(initialSoundDictQueue).Take(1))
{
correctSoundDict = key.ToString();
}
//Choose Correct Card
foreach (object value in RandomValues(cardQueue).Take(1))
{
correctCard = (GameObject)value;
correctCard.AddComponent<CorrectCard>();
}
//Reveal Correct Card
foreach (object key in RandomKey(initialSoundDictQueue[correctSoundDict]).Take(1))
{
string stringKey = key.ToString();
correctObject = initialSoundDictQueue[correctSoundDict][stringKey];
Instantiate(correctObject, correctCard.transform.position, Quaternion.identity, correctCard.transform.GetChild(0));
TextMeshPro title = correctCard.transform.GetChild(1).GetComponent<TextMeshPro>();
string noSpaceTitle = stringKey.Replace(" ", string.Empty);
title.text = noSpaceTitle;
TextMeshPro subhead = correctCard.transform.GetChild(2).GetComponent<TextMeshPro>();
subhead.text = stringKey;
}
//Choose Incorrect Dictionary
foreach (object key in RandomKey(initialSoundDictQueue).Take(1))
{
incorrectSoundDict = key.ToString();
}
//Choose First Incorrect Card1
foreach (object value in RandomValues(cardQueue).Take(1))
{
incorrectCard1 = (GameObject)value;
}
;
//Reveal First Incorrect Card
foreach (object key in RandomKey(initialSoundDictQueue[incorrectSoundDict]).Take(1))
{
string stringKey = key.ToString();
incorrectObject1 = initialSoundDictQueue[incorrectSoundDict][stringKey];
Instantiate(incorrectObject1, incorrectCard1.transform.position, Quaternion.identity, incorrectCard1.transform.GetChild(0));
TextMeshPro title = incorrectCard1.transform.GetChild(1).GetComponent<TextMeshPro>();
string noSpaceTitle = stringKey.Replace(" ", string.Empty);
title.text = noSpaceTitle;
TextMeshPro subhead = incorrectCard1.transform.GetChild(2).GetComponent<TextMeshPro>();
subhead.text = stringKey;
}
//Choose Second Incorrect Card1
foreach (object value in RandomValues(cardQueue).Take(1))
{
incorrectCard2 = (GameObject)value;
}
//Reveal Second Incorrect Card
foreach (object key in RandomKey(initialSoundDictQueue[incorrectSoundDict]).Take(1))
{
string stringKey = key.ToString();
incorrectObject2 = initialSoundDictQueue[incorrectSoundDict][stringKey];
Instantiate(incorrectObject2, incorrectCard2.transform.position, Quaternion.identity, incorrectCard2.transform.GetChild(0));
TextMeshPro title = incorrectCard2.transform.GetChild(1).GetComponent<TextMeshPro>();
string noSpaceTitle = stringKey.Replace(" ", string.Empty);
title.text = noSpaceTitle;
TextMeshPro subhead = incorrectCard2.transform.GetChild(2).GetComponent<TextMeshPro>();
subhead.text = stringKey;
}
}
public IEnumerable<TValue> RandomValues<TKey, TValue>(IDictionary<TKey, TValue> dict)
{
System.Random rand = new System.Random();
List<TValue> values = Enumerable.ToList(dict.Values);
int size = dict.Count;
while (true)
{
TValue chosenValue = values[rand.Next(size)];
if (vetList.Contains(chosenValue.ToString()))
{
//print("Contains");
}
else
{
vetList.Add(chosenValue.ToString());
yield return chosenValue;
}
}
}
public IEnumerable<TKey> RandomKey<TKey, TValue>(IDictionary<TKey, TValue> keyQueue)
{
System.Random rand = new System.Random();
List<TKey> Keys = Enumerable.ToList(keyQueue.Keys);
int size = keyQueue.Count;
while (true)
{
TKey chosenKey = Keys[rand.Next(size)];
if (vetList.Contains(chosenKey.ToString()))
{
print("Contains");
}
else
{
vetList.Add(chosenKey.ToString());
yield return chosenKey;
}
}
}
This is where it freezes when I execute resetExercise() after interaction with a card. Test will print so I assume the for loop is what's freezing it? Apologies if the answer is obvious.
public void resetExercise () {
GameObject ShuffleObject = GameObject.Find("InitialSoundCardShuffler");
CardShuffler = ShuffleObject.GetComponent<InitialSoundCardShuffler>();
CardShuffler.initialSoundCounter++;
CardShuffler.progressBar.value = CardShuffler.CalculateProgress();
CardShuffler.ShuffleCards();
}
the number of calls to the random methods that are allowed before enter a infinite loop, strong depends of their respective dict size, what happen if you replace: in RandomValues()
while (true){
by
while (vetList.count < size)
and create a vetList$$anonymous$$
to hold the values generated in Random$$anonymous$$ey()
, also change inside the while
of Random$$anonymous$$ey()
:
while (vetList$$anonymous$$.count<size)
{
T$$anonymous$$ey chosen$$anonymous$$ey = $$anonymous$$eys[rand.Next(size)];
if (vetList$$anonymous$$.Contains(chosen$$anonymous$$ey.ToString()))
{
print("Contains");
}
else
{
vetList$$anonymous$$.Add(chosen$$anonymous$$ey.ToString());
yield return chosen$$anonymous$$ey;
}
}
if you still have cpu overloads, probably will need to change some desing, like verify if you need a script to check if a card is correct (maybe you store some values there, idk) otherwise, use a bool or change tag, or use a comparer inside a list of string, maybe you cannot do the comparision of all TValues already chosen on other, more efficient way?, you know, I dont have all the proyect so I can only make assumptions about how optimize it, you are on the field :)
Answer by Diesign · Feb 06, 2019 at 07:26 AM
It was because it ran out of inputs and went into an infinite loop while checking the vetlist and having not other dicts to choose from.
Your answer
Follow this Question
Related Questions
Editor freezes after 'killing' an enemy but not every time 1 Answer
Unity freezes when I run this and I have no idea why, please help 0 Answers
If statement in for loop not working after fail 0 Answers
How to get a for loop to run once per coroutine? 1 Answer
Why does my game crash on my mobile when I try to load the scene with this interstitial ad script? 0 Answers