if (ToastTimeout > 0)
{
for (int i = 0; i < StringGrid.Count; i++)
{
StringGrid[length + i].GetComponent<Renderer>().material.SetColor("_Color", new Color32(255, 255, 255, (byte)(255 * ToastTimeout / Scale)));
}
ToastTimeout -= Time.deltaTime;
}
It runs correctly until i is 4, then at the very end of the For loop, it switches back to 0. But there are more than 4 elements in the dictionary StringGrid (Yes, I know they are GameObjects but it’s called StringGrid). It never leaves the For loop, because the condition is never met, and it never runs the line below the For loop, which is crucial.
StringGrid is a dictionary yeah? When you access a dictionary’s indexer with a key that doesn’t exist, it adds a key-value pair for that key. So you are probably just adding infinite members to your dictionary.
Not sure what you’re trying to accomplish here, but you will need to rethink your approach. A regular List collection is probably more appropriate.
You really shouldn’t write lines of code like line 5 in that example, as well. Break it down and make it easier to understand.
Also worth noting that when you access the .material property of a renderer, it creates an instances of that material. You need to destroy this object when no longer needed, otherwise this creates a memory leak.
Needless to say, fundamental language features like for-loops DO work. If they aren’t working, there is something wrong with your code.
Break it up, practice social distancing in your code, one thing per line please.
“Programming is hard enough without making it harder for ourselves.” - angrypenguin on Unity3D forums
“Combining a bunch of stuff into one line always feels satisfying, but it’s always a PITA to debug.” - StarManta on the Unity3D forums
I would even add that if you’re at the point where you think the for() loop doesn’t work, then just delete the line of code and re-engineer the solution from first principles, asking yourself the standard questions for any loop: where does it start, where does it end, and what is iterating it?
Like @spiney199 mentioned if you’re a Dictionary and the entry doesn’t exist it’s going to add a new one to the collection. The advantage and disadvantage to a for loop is that you can add or remove entries of a collection and it can change the end condition. If you’re continuously triggering the Dictionary to add new entries with every pass of the loop then Count will continue to rise every pass and the loop becomes infinite.
I do understand this, however I can guarantee this is not the problem I’m having. If it was, i would just keep increasing. However, as it is, it goes up to 4 and then resets. But there are definitely more than 4 elements in that dictionary. Also, as I’m accessing the attributes of each value, I’m fairly sure it won’t create a new value, if it does it would throw an error.
Right, it’s in fixedUpdate, so it just doesn’t finish the for loop and instead restarts the fixedupdate loop completely over, never executing the bottom code.
Loops don’t just not finish, and code doesn’t get skipped unless you specifically return from execution early (either by specifically calling return; or by throwing an exception).
You need to keep debugging to see what’s going on here. Are you sure an exception is not being thrown?
Additionally, why is a dictionary being used here as a opposed to a List? And why is non-physics code being used in FixedUpdate?
I moved it to Update, it did the same thing, BUT you did get me to click the “break on all exceptions” button I conveniently missed and found out that the way I indexed the dictionary was by .5 increments and I didn’t account for that. Because it couldn’t find the GameObjects, it threw an error (And did NOT create more pairs as some have said). Now it works!
StringGrid[length + i] will add new item (and in this case, null item) to the dictionary if length + i is not found. This is how dictionary is implemented. So StringGrid.Count will just keep increasing leads to an infinite loop.
I was too before I double checked myself and found out I was wrong.
I will say, it is weird that getting a value and assigning a value via the key has two different behaviours if the key doesn’t exist. But I guess it was a decision from a long time ago that can’t be changed now.
And I suspect that’s the root of it. My memory is quite distinctly that accessing a non-existent key causes it to be added to the collection. I either did not learn, or have somehow since forgotten, the distinction between read and write access in this case.
I believe you’re both probably right, IF I wasn’t accessing attributes of the keys only associated with GameObjects. If I was just accessing them and not their attributes, it would probably have made a new pair.
Well no, it would not have made a difference. Accessing the dictionary at all via the indexer with a key that doesn’t exist, it will throw an exception, as it states in the documentation I linked above:
If the specified key is not found, a get operation throws a KeyNotFoundException, and a set operation creates a new element with the specified key.
So the exception starts and ends value = dictionary[keyNotInDictionary]; and whether you try to do anything with the value after that point is after the exception has been thrown.