Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Creating a Generic Method for button initialisation

Discussion in 'Scripting' started by kensarto17, Feb 20, 2020.

  1. kensarto17

    kensarto17

    Joined:
    Nov 11, 2017
    Posts:
    27
    As the title mentions, my current goal is to create a method that performs the following
    Code (CSharp):
    1. Button cardboardSignButton = Instantiate(prefabButton, upgradeButtonParentTransform);
    2.  
    3.         cardboardSignButton.GetComponentInChildren<Text>().text = GameManager.Instance.cardboardSign.upgradeName;
    4.         cardboardSignButton.gameObject.SetActive(false);
    5.  
    6.         EventTrigger.Entry entry = new EventTrigger.Entry();
    7.         entry.eventID = EventTriggerType.PointerEnter;
    8.         entry.callback.AddListener((data) => {
    9.             DisplayTooltipUpgrades(GameManager.Instance.cardboardSign);
    10.         });
    11.         EventTrigger.Entry exit = new EventTrigger.Entry();
    12.         exit.eventID = EventTriggerType.PointerExit;
    13.         exit.callback.AddListener((data) => {
    14.             HideTooltip();
    15.         });
    16.         EventTrigger.Entry click = new EventTrigger.Entry();
    17.         click.eventID = EventTriggerType.PointerDown;
    18.         click.callback.AddListener((data) => {
    19.             GameManager.Instance.cardboardSign.BuyCardboardSign();
    20.         });
    21.         cardboardSignButton.GetComponent<EventTrigger>().triggers.Add(entry);
    22.         cardboardSignButton.GetComponent<EventTrigger>().triggers.Add(exit);
    23.         cardboardSignButton.GetComponent<EventTrigger>().triggers.Add(click);
    However, i do not just want to do it once, for one button, but i want to do it for multiple (20+ at the current moment with more on the way) buttons each with different methods, text values and parentTransforms.

    The parameters for the method when it comes to changing text and transform is as easy as adding them like any other method. But what I am wondering is, how and if you can add a method as a parameter for this method, for use in the section where i add a listener to the click event trigger.

    My suspicions lead me to believe it has something to do with delegates but they're hard to wrap my head around. So, how can I put a method as a parameter, so that the method i am creating can attach that to my buttons.

    Edit: The reason I want this is to save on 18 lines of code that need to have 12 or so changes made each time, by replacing it with a single line calling the method with perhaps 3-4 parameters.
     
  2. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,556
    Isn't this what we have prefabs for? Parametrize the important stuff, create one button, make it a prefab, and automate the rest by spawning or using Editor. I know it doesn't always work, but your code snippet looks quite generic.
     
  3. SisusCo

    SisusCo

    Joined:
    Jan 29, 2019
    Posts:
    1,135
    AddListener takes a UnityAction<BaseEventType> argument. You can see this simply by mouseovering the method in your IDE.

    parameter type.png

    So the code for creating your button would end up looking something like this:
    Code (CSharp):
    1. public static Button CreateButton(Button prefab, Transform parent, string text, UnityAction<BaseEventData> onPointerEnter, UnityAction<BaseEventData> onPointerExit, UnityAction<BaseEventData> onPointerDown)
    2. {
    3.     var button = Instantiate(prefab, parent);
    4.     button.GetComponentInChildren<Text>().text = text;
    5.     button.gameObject.SetActive(false);
    6.  
    7.     var entry = new EventTrigger.Entry()
    8.     {
    9.         eventID = EventTriggerType.PointerEnter
    10.     };
    11.     entry.callback.AddListener(onPointerEnter);
    12.  
    13.     var exit = new EventTrigger.Entry()
    14.     {
    15.         eventID = EventTriggerType.PointerExit
    16.     };
    17.     exit.callback.AddListener(onPointerExit);
    18.  
    19.     var click = new EventTrigger.Entry()
    20.     {
    21.         eventID = EventTriggerType.PointerDown
    22.     };
    23.     click.callback.AddListener(onPointerDown);
    24.  
    25.     button.GetComponent<EventTrigger>().triggers.Add(entry);
    26.     button.GetComponent<EventTrigger>().triggers.Add(exit);
    27.     button.GetComponent<EventTrigger>().triggers.Add(click);
    28.  
    29.     return button;
    30. }
     
    Last edited: Feb 20, 2020
    kensarto17 likes this.
  4. kensarto17

    kensarto17

    Joined:
    Nov 11, 2017
    Posts:
    27
    Are there any changes that need to be made to the methods that I am calling for them to work in the above method? I have implemented it, and I am receiving the following error:

    Assets\Scripts\SceneManager.cs(1213,136): error CS1503: Argument 4: cannot convert from 'void' to 'UnityEngine.Events.UnityAction<UnityEngine.EventSystems.BaseEventData>'

    the same occurs for argument 5 and 6 as well, all of the methods im calling look like this more or less:

    Code (CSharp):
    1. public void BuyUniform() {
    2.         if (CharacterManager.Instance.taels.quantity >= 25) {
    3.             CharacterManager.Instance.taels.QuantityDecrease (25);
    4.             TierUp ();
    5.         }
    6.     }
    Edit: below i have attached the create button method

    Code (CSharp):
    1. upgradeButtons.Add(CreateNewButton(prefabButton, upgradeButtonParentTransform, GameManager.Instance.tuition.upgradeName, DisplayTooltipUpgrades(GameManager.Instance.tuition), HideTooltip(), GameManager.Instance.tuition.BuyTuition()));
     
    Last edited: Feb 20, 2020
  5. SisusCo

    SisusCo

    Joined:
    Jan 29, 2019
    Posts:
    1,135
    You can create the UnityActions just like you did before using lambda expressions
    Code (CSharp):
    1. CreateButton(prefabButton, upgradeButtonParentTransform, GameManager.Instance.tuition.upgradeName,
    2.     (data)=>DisplayTooltipUpgrades(GameManager.Instance.tuition),
    3.     (data)=>HideTooltip(),
    4.     (data)=>GameManager.Instance.tuition.BuyTuition());
     
    kensarto17 likes this.
  6. kensarto17

    kensarto17

    Joined:
    Nov 11, 2017
    Posts:
    27
    It works brilliantly and looks beautiful in comparison to the previous work i had, thank you very much.
     
    SisusCo likes this.
  7. SisusCo

    SisusCo

    Joined:
    Jan 29, 2019
    Posts:
    1,135
    Awesome, I'm glad I could help!