Home > Software design >  Is this an alright method for buttons?
Is this an alright method for buttons?

Time:04-28

I'm practicing with buttons in Unity and I'm trying to figure out how I can assign different methods to a button without using the OnClick thing in the inspector so I came up with this.

public class UIButtons : MonoBehaviour
{
    void Start()
    {
        var buttons = FindObjectsOfType<Button>(); //I should probably have this outside of this method
        foreach (Button button in buttons)
        {
            button.onClick.AddListener(() => ButtonPressed(button));
        }
    }

    void ButtonPressed(Button button)
    {
        switch (button.name)
        {
            case "MMPlayButton": //The main menu play button
                Debug.Log("Play button pressed");
                break;
            case "PlayButton": 
                Debug.Log("Play button pressed");
                break;
            case "SettingsButton":
                Debug.Log("Settings button pressed");
                break;
            case "QuitButton":
                Debug.Log("Quit button pressed");
                break;
            default:
                Debug.LogWarning("Button doesn't have a case: "   button.name); 
                //could do some kind of pop up message saying the button pressed isn't available or something
                break;
        }
    }
}

I know this can work, however, I'd imagine this is a horrible way to do things because it's using the name so if I were to change the name or make a typo it breaks, or an issue I did encounter was if buttons have the same name, and if I add more buttons I'd have to add more cases and then it would probably turn out to be a giant mess.

I could be wrong though and maybe this is an alright idea, but I doubt it so looking for some help with this.

CodePudding user response:

I know this won't be a good answer but if I were you, I would make different files for different buttons. Like SettingButton.cs, PlayButton.cs etc.

This approach will not add a huge amount of burden to your code but as the functionalities of your buttons increase, this approach will greatly help to keep your code organized.

CodePudding user response:

You can simplify this by using inheritance. Create a base class for all of your buttons to use, ie. UIButtonBase that has the OnButtonPressed virtual method. Then create specific buttons that inherit this base class and override the OnButtonPressed method.

Base Class

public class UIButtonBase: MonoBehaviour
{
    protected virtual void Awake()
    {
        var button = GetComponent<Button>();
        if (button)
        {
            button.onClick.AddListener(() => OnButtonPressed());
        }
        else
        {
            Debug.Log(name   " does not have a Button component!");
        }
    }
    
    protected virtual void OnButtonPressed()
    {
        Debug.Log("UIButtonBase::OnButtonPressed()");
    }
}

Specific implementation of a button

public class SettingsButton : UIButtonBase
{
    protected override void OnButtonPressed()
    {
        Debug.Log("SettingsButton::OnButtonPressed()");

        // If you want the base functionality as well, add..
        //
        base.OnButtonPressed();
    }
}

For setup, create a button and add this script to it. You may need to change the GetComponent in Awake (UIButtonBase) to GetComponentInParent or GetComponentInChildren, depending on your gameobjects hierarchy. You could also expose the Button component in the UIButtonBase script and use that reference.

  • Related