Programatically set button OnClick not producing expected results.

Hi! I’m new to unity and I tried to make a UI which is a panel and contains 8 buttons. When something in my game is selected, the UI is updated so that the button sprites of the are updated to the sprite of a ‘unit’ that’s selected. And then depending on if the unit is in the selected group or just happens to be in the same space it changes the alpha value. So what I’m running into is when I update the buttons I also update the onclick event so that it either moves the unit out of the active group (if it’s in the active group) or into the active group if it’s not already.

So I’m running into this issue where the units aren’t being moved correctly and I really think it’s coming down to my handling of the UI. Here’s the main things I’m seeing:

  • if I try to remove a unit from the active group it’s supposed to create a new group and put the unit into that. But what I’m getting after I do it once, is that the button is creating more than one new stack, and although they’re empty they’re still getting created.
  • If I add a unit to a group when I try to remove I’m getting out of range exceptions with my list that manages the units. And some other times it will just completely remove the a group of units rather than the individual.

Here’s how I’m attempting to set my UI when I select a group of units:

public void UpdateUnitStackPanel() {
        ClearStackPanel();
        AddActiveStackToStackPanel();
        if(unit_stacks_for_UI != null)
            Debug.Log("unit_stacks_for_UI.Count: " + unit_stacks_for_UI.Count);
        AddSecondaryStacksToStackPanel();
        StackPanelSetEmptyButtons();
    }

    public void ClearStackPanel() {
        Button button;
        for (int i = 0; i < UnitStackPanel.transform.childCount; i++) {
            button = GetUnitStackPanelUnitDisplay(i);
            button.image.overrideSprite = null;
            button.image.color = new Color(1f, 1f, 1f, 1f);
            button.onClick.AddListener(() => { });
        }
    }

    private void AddActiveStackToStackPanel() {
        for (int i = 0; i < active_unit_stack.Count; i++) {
            int index = i;
            var button = GetUnitStackPanelUnitDisplay(i);
            button.image.overrideSprite = active_unit_stack.units.Units[i].GetComponent<CombatUnit>().sprite.sprite;
            button.image.color = new Color(1f, 1f, 1f, 1f);
            if (unit_stacks_for_UI != null && unit_stacks_for_UI.Count > 0) {
                button.onClick.AddListener(delegate { active_unit_stack.MoveUnitToStack(index, unit_stacks_for_UI[0]); });
            }
            else {
                button.onClick.AddListener(delegate { active_unit_stack.MoveUnitToNewStack(index); });
            }
        }
    }

    private void RemoveEmptySecondaries() {
        if (unit_stacks_for_UI == null) return;
        var total_stacks = unit_stacks_for_UI.Count - 1;
        for (int i = total_stacks; i >= 0; i--) {
            if(unit_stacks_for_UI[i].Count < 1) {
                Debug.Log("stack[" + i + "] has no units");
                Destroy(unit_stacks_for_UI[i].gameObject);
                unit_stacks_for_UI.RemoveAt(i);
            }
        }
    }

    private void AddSecondaryStacksToStackPanel() {
        if (unit_stacks_for_UI == null) return;
        RemoveEmptySecondaries();
        Button button;
        var button_index = active_unit_stack.Count;
        for (int i = 0; i < unit_stacks_for_UI.Count; i++) {
            UnitStack working_stack = unit_stacks_for_UI[i];
            Debug.Log("working_stack" + working_stack.Count);
            for (int c = 0; c < working_stack.Count; c++) {
                int index = c;
                button = GetUnitStackPanelUnitDisplay(button_index);
                button.image.overrideSprite = working_stack.units.Units[c].GetComponent<CombatUnit>().sprite.sprite;
                button.image.color = new Color(1f, 1f, 1f, 0.5f);
                button.onClick.AddListener(delegate { working_stack.MoveUnitToStack(index, active_unit_stack); });
                button_index++;
            }
        }
    }

    private void StackPanelSetEmptyButtons() {
        //var index = GetUnitCount();
        Button button;
        for (int i = GetUnitCount; i < UnitStackPanel.transform.childCount; i++) {
            button = GetUnitStackPanelUnitDisplay(i);
            button.image.overrideSprite = null;
            button.image.color = new Color(1f, 1f, 1f, 1f);
            button.onClick.AddListener(() => { });
        }

    }

Am I setting the AddListeners properly? I should note, I have a non programatically set button, which does an initial test generation, and it makes the groups how I’d expect. No extras.

It seems like your not actually removing the listener, but instead you’re adding an empty one.

button.onClick.AddListener(() => { });

You’ll want to use button.onClick.RemoveListener(callback)

Thanks so much! This really helped me out!