- Home /
The question is answered, right answer was accepted
My For Loop is skipping past the first iteration, I'm losing my mind
Hey guys,
So essentially, I have a radial menu, with separate child objects for icons I want to add in as you pick up objects in the game. All I'm trying to do is enable the respective icon when you pick up the item. It's working, except it's skipping past the first iteration in my for loop below in ActivateIcon().
What's weird is, If I open my radial menu to the correct submenu, then close it, THEN the icon is added in properly.. I've been staring at this for 2 days straight and I'm completely lost.
So the for loop is checking an int Indexvalue I set in a .asset file created via a ScriptableObject. I've triple checked that.
Let me know if you need any more information, but anything you could do to help would be greatly appreciated, maybe I'm just missing something simple?
public class ActivateSpellIconOnPickUp : MonoBehaviour {
private SpellInvManager spellManager;
public List<GameObject> defenseIcons = new List<GameObject>();
public GameObject[] offenseIcons;
public GameObject defCanvas;
public GameObject offCanvas;
public GameObject pieMenu;
private bool defHasBeenUsed;
private bool offHasBeenUsed;
private PieMenu pieMenuScript;
public float howLongPieMenuIsOpenFor = .65f;
private void Start()
{
spellManager = FindObjectOfType<SpellInvManager>();
spellManager.OnPickupSpell += ActivateIcon; //subscribe AddSpell to the ONPickupSpell event
defHasBeenUsed = false;
offHasBeenUsed = false;
pieMenuScript = FindObjectOfType<PieMenu>();
}
private void ActivateIcon(Spell spell)
{
if (spell.spellSelection == Spell.SpellType.Defensive)
{
defCanvas.SetActive(true); //activate DefenseCanvas so a reference can be generated
pieMenuScript.pieSelection = PieMenu.spellMenuSelection.Defensive; //change the spellMenuSelection so you can actually control the menu once it opens
//TODO: Add an animation to the spell wheel and the spell being added to make it look more fancy
if (!defHasBeenUsed)
{
defenseIcons = GameObject.FindGameObjectsWithTag("DefenseIcon").OrderBy(go => go.name).ToList(); //find array of Gameobjects and sort the array so the icons appear in the same place everytime
defHasBeenUsed = true; //you can't get a reference to an inactive Gameobject, I only want the Array generated one time
}
for (int i = 0; i < defenseIcons.Count; i++)
{
if (i == spell.spriteIndexNumber)
{
Image iImage = defenseIcons[i].GetComponent<Image>();
iImage.enabled = true;
}
}
}
else if (spell.spellSelection == Spell.SpellType.Offensive)
{
offCanvas.SetActive(true); //activate OffenseCanvas so a reference can be generated (Inactive Gameobjects can't be found at runtime)
pieMenuScript.pieSelection = PieMenu.spellMenuSelection.Offensive; //change the spellMenuSelection so you can actually control the menu once it opens
//TODO: Add an animation to the spell wheel and the spell being added to make it look more fancy
if (!offHasBeenUsed)
{
offenseIcons = GameObject.FindGameObjectsWithTag("OffenseIcon").OrderBy(go => go.name).ToArray(); //find array of Gameobjects and sort the array so the icons appear in the same order evertime (same place in menu)
offHasBeenUsed = true; //ensure this if statement only runs one time
}
for (int i = 0; i < offenseIcons.Length; i++)
{
if (i == spell.spriteIndexNumber)
{
Image iImage = offenseIcons[i].GetComponent<Image>();
iImage.enabled = true; //actually activate the spell icon. Took WAY too much code to get this done
}
}
}
}
I still dont understand what you wanted to do there, in particular, did you realize that this piece of code:
for (int i = 0; i < defenseIcons.Count; i++)
{
if (i == spell.spriteIndexNumber)
{
Image iImage = defenseIcons[i].GetComponent<Image>();
iImage.enabled = true;
}
}
is exactly the same to write
if (spell.spriteIndexNumber< defenseIcons.Count)
{
Image iImage = defenseIcons[spell.spriteIndexNumber].GetComponent<Image>();
iImage.enabled = true;
}
this way to write code is... unusual, and you don't care of performace, just an opinion
I'm not the most experienced programmer, but I learn lots from making stupid little mistakes like the one you pointed out, thanks for your insight there! Your way is definitely more performance-friendly.
Answer by faldor20 · May 15, 2019 at 05:03 AM
What i would suggest is to debug log out the value of "i" in your for loop followed by "spell.spriteIndexNumber" and see if it really is skipping the first value. Alternatively you could use a debugger in the ide your using. Set a breakpoint in the first step of the for loop then look at the variables you are interested in ("i" and "spell.spriteIndexNumber") and then use the step forward button to watch the flow of the for loop.
Answer by bwaite87 · May 15, 2019 at 05:24 PM
Thanks Faldor20, I've learned a few things today :) This didn't help me solve my issue, but I figured it out and it was a completely different script that was setting SetActive(false) for my gameObject in the onEnable, which I did for good reason at the time...but essentially that script was setting the Image to inactive, and right before my for loop it was trying to activate it, and they were essentially happening at the same time.
Thanks again for your suggestion though, I'll keep that debug feature in mind in the future!
$$anonymous$$ostly i was suggesting you do that to confirm whether your claim at the beginning was true. Whether or not your for loop was truly missing its first run.
Follow this Question
Related Questions
Use The Force Luke 1 Answer
What is the order of execution in a for loop? 1 Answer
Use for-i-loop var outside the loop 2 Answers
Problem with raycasts in a for loop 2 Answers
Setting up an 2d grid in C# 3 Answers