Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Resolved Button onClick doesn't work (Instantiated button)

Discussion in 'Scripting' started by OwenTheProgrammer, May 19, 2021.

  1. OwenTheProgrammer

    OwenTheProgrammer

    Joined:
    May 19, 2021
    Posts:
    16
    Hi

    So my problem is: if i instantiate my button (not a prefab) and then i add code to my instantiated game object by doing:
    Code (CSharp):
    1. GameObject cloneTile = Instantiate(GreenTile, ClonesParent.transform);
    2. cloneTile.AddComponent<TileOnClick>();
    3. cloneTile.SetActive(true);
    This is the code i added:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3.  
    4. public class TileOnClick : MonoBehaviour
    5. {
    6.  
    7.     private Button tile;
    8.  
    9.     public void Start()
    10.     {
    11.  
    12.         tile = GetComponent<Button>();
    13.         tile.interactable = true;
    14.         tile.onClick.AddListener(TilePressed);
    15.  
    16.     }
    17.  
    18.     public void TilePressed()
    19.     {
    20.  
    21.         Debug.Log("It works");
    22.  
    23.         Game.score += 20;
    24.  
    25.         tile.interactable = false;
    26.  
    27.     }
    28.  
    29. }
    But the problem is when i click on the button nothing happens.

    Can please someone help me?

    Maybe this is an easy solution but i don't know how to solve it.
     
    Last edited: May 19, 2021
  2. Johan_Liebert123

    Johan_Liebert123

    Joined:
    Apr 15, 2021
    Posts:
    474
    Have you actually added the function to OnClick on the button
     
  3. OwenTheProgrammer

    OwenTheProgrammer

    Joined:
    May 19, 2021
    Posts:
    16
    How do you mean? I added it with this line of code:
    Code (CSharp):
    1. tile.onClick.AddListener(TilePressed);
     
  4. Johan_Liebert123

    Johan_Liebert123

    Joined:
    Apr 15, 2021
    Posts:
    474
    If you go to the Hierarchy and click on the button and scroll down there will be a box which says OnClick as shown below
    upload_2021-5-19_19-7-44.png

    Then you gotta click the plus function and you'll get something like this
    upload_2021-5-19_19-8-24.png

    Then the object which contains the script you drag it to the place where it says 'None (Object)' and then you add the function like this
    upload_2021-5-19_19-9-39.png

    In you case you would find the script (TileOnClick) then add the function which would be
    TilePressed()

    Easy as that
     
  5. OwenTheProgrammer

    OwenTheProgrammer

    Joined:
    May 19, 2021
    Posts:
    16
    Yes i did that with other buttons and that works, but it is an instantiated button (a clone) so you don't see it in the hierarchy. So that is not an option
     
  6. Johan_Liebert123

    Johan_Liebert123

    Joined:
    Apr 15, 2021
    Posts:
    474
    One problem could be when you instantiate a button, it might loose it's reference for any OnClick event which depends on it, that could be the problem but nothing else is hitting my mind right now, maybe wait for someone else with more knowledge who would be willing to help you.
     
  7. OwenTheProgrammer

    OwenTheProgrammer

    Joined:
    May 19, 2021
    Posts:
    16
    Yeah i also thought about that but i don't know how to get back the reference manualy, maybe you know it? And Thanks for helping me!
     
  8. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    8,188
    I would make your instantiated button a more complete prefab that you instantiate, which should already have the script and what it needs to functions as part of it. That way you can pre-setup the On-click functions rather than needing to subscribe.

    If you have dynamic methods that needs to be called, I would use C# events or any other delegate system to handle that, and your onclick event just calls that event.

    Let me know if you need a more detailed explanation of setting that up.
     
  9. OwenTheProgrammer

    OwenTheProgrammer

    Joined:
    May 19, 2021
    Posts:
    16
    Hi thanks for your reaction, can you explain me how you can do that with the events?
     
  10. TheNightglow

    TheNightglow

    Joined:
    Oct 1, 2018
    Posts:
    201
    in this case you probably do not want to use Start() since you are adding your component directly anyway, you could just call an initialization function manually right after that...

    im honestly not sure if Start gets executed right after AddComponent when the object is disabled..., have you tried to look if your Start function gets executed using a Debug.Log()? because i dont think it gets called there

    in either way you dont have to worry about assigning methods onclick in the inspector in the editor like other answers say here,
    tile.onClick.AddListener does the same but is better practice
    so in any way that is not the problem

    maybe try calling your initialization method right after adding the component (herefor either define a new function that does what Start is currently doing or use Start as an initialization function)

    Code (CSharp):
    1. GameObject cloneTile = Instantiate(GreenTile, ClonesParent.transform);
    2. TileOnClick tileOnClick = cloneTile.AddComponent<TileOnClick>() as TileOnClick;
    3. tileOnClick.Start(); //or tileOnClick.Initialize() if you define it as a function called Initialize() :)
    4. cloneTile.SetActive(true);
    or alternatively do cloneTile.SetActive(true); befor adding the component
     
    Last edited: May 19, 2021
  11. OwenTheProgrammer

    OwenTheProgrammer

    Joined:
    May 19, 2021
    Posts:
    16
    Hi

    I tested youre code and i added some Debug.Log() lines in my code. And i what is see is that everything works except the method Tilepressed. The start function works but if i do tile.onClick.Addlistener(Tilepressed); that doesn't do anything, because if i click on the button nothing happens and i don't get some feedback from the debugger. Maybe you know how it comes.
     
  12. TheNightglow

    TheNightglow

    Joined:
    Oct 1, 2018
    Posts:
    201
    and other buttons in the same project work? because if they dont you simply need to add an eventmanager to the scene

    alternatively, last things I can imagine:
    - are there any errors in the console?
    - does GreenTile actually have a button attached to it and is this (or rather its clone) really the button you are trying to press?
     
    Last edited: May 20, 2021
  13. OwenTheProgrammer

    OwenTheProgrammer

    Joined:
    May 19, 2021
    Posts:
    16
    Yes, all my other buttons in my project work except my cloned buttons. And yes the GreenTile has a button attached to it, i checked it with the debug logger. And there are no errors in the console. So i really don't know what is wrong. I hope you find a solution, because i already put so much time in it and i still do not have a solution.
     
  14. OwenTheProgrammer

    OwenTheProgrammer

    Joined:
    May 19, 2021
    Posts:
    16
    Here you guys have a little update of my code so you guys can maybe understand it better.

    Code (CSharp):
    1. GameObject cloneTile = Instantiate(GreenTile, ClonesParent.transform);
    2. cloneTile.SetActive(true);
    3. TileOnClick tileOnClick = cloneTile.AddComponent<TileOnClick>() as TileOnClick;
    4. tileOnClick.Start();
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3.  
    4. public class TileOnClick : MonoBehaviour
    5. {
    6.  
    7.     private Button tile;
    8.  
    9.     public void Start()
    10.     {
    11.  
    12.         Debug.Log("Start function is executed");
    13.  
    14.         tile = gameObject.GetComponent<Button>();
    15.      
    16.         Debug.Log(tile);
    17.      
    18.         tile.interactable = true;
    19.         tile.onClick.AddListener(TilePressed);
    20.  
    21.     }
    22.  
    23.     public void TilePressed()
    24.     {
    25.  
    26.         Debug.Log("It works");
    27.  
    28.         Game.score += 20;
    29.  
    30.         tile.interactable = false;
    31.  
    32.     }
    33.  
    34. }
     
  15. OwenTheProgrammer

    OwenTheProgrammer

    Joined:
    May 19, 2021
    Posts:
    16
    Hi

    Stil don't know what the problem is :(

    I hope i can find a solution quickly
     
  16. OwenTheProgrammer

    OwenTheProgrammer

    Joined:
    May 19, 2021
    Posts:
    16
    Hi guys

    I just found out that if i add this single line of code:
    Code (CSharp):
    1. Tile.onClick.Invoke();
    in my start function then it works but it's not exactly what i want. Because when my button spawns it executes the code already in my start function. What means you get score without pressing the button. And after that if i press my button it does nothing again.
     
    Last edited: May 21, 2021
  17. OwenTheProgrammer

    OwenTheProgrammer

    Joined:
    May 19, 2021
    Posts:
    16
    Hi

    I still didn't find any solution for my problem.
    My problem is: If i press on my instantiated button the onClick function does not work i guess.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3.  
    4. public class TileOnClick : MonoBehaviour
    5. {
    6.  
    7.     private Button tile;
    8.  
    9.     public void Start()
    10.     {
    11.        
    12.         Debug.Log("Start function is executed");
    13.  
    14.         tile = gameObject.GetComponent<Button>();
    15.  
    16.         Debug.Log(tile);
    17.  
    18.         tile.interactable = true;
    19.         tile.onClick.AddListener(TilePressed);
    20.  
    21.     }
    22.  
    23.     public void TilePressed()
    24.     {
    25.        
    26.         tile.interactable = false;
    27.  
    28.         Debug.Log("It works");
    29.  
    30.         Game.score += 20;
    31.  
    32.     }
    33.  
    34. }
    The function TilePressed don't get executed. And i checked with a debug logger if the button is the right one. So that is not the problem. That's why i don't understand what is wrong, why isn't my code getting executed?

    Hopefully you guys know an answer.

    Kind regards
    Owen
     
  18. TheNightglow

    TheNightglow

    Joined:
    Oct 1, 2018
    Posts:
    201
    I wonder... when you hover with the mouse over the button in the game view, does the button change color like a normal button? (interactable ui objects usually have a color pallet they use depending on their state, like on default they get a bit darker when the mouse hovers over it)

    if it does not change color your scripts are not the problem, but rather your UI setup in the scene

    could it be that another transparent UI object is on top of the button and catching the UI clicks?
    or could it be that the button itself has a zero size in the scene?

    could you show how the instantiated button looks in game and show the inspector of it in the unity scene?
     
  19. OwenTheProgrammer

    OwenTheProgrammer

    Joined:
    May 19, 2021
    Posts:
    16
    Hi

    It does not change its color when i hover over the button.

    There is also no other transparent UI object on top of it. I don't think the button has a zero size in the scene because i can see the button.

    I will show you my game scene in a minute. By the way it is a piano tiles game so the buttons are moving, maybe that is the problem?
     
  20. OwenTheProgrammer

    OwenTheProgrammer

    Joined:
    May 19, 2021
    Posts:
    16
    Hi

    Here you have a video of my project. (If i click on the button it doesn't work if it would work there would be added score)

     
  21. TheNightglow

    TheNightglow

    Joined:
    Oct 1, 2018
    Posts:
    201
    buttons moving in itself is not a problem, tho more interesting than seeing the button ingame is actually seeing the scene and scene hirachy and the button inspector

    as in dont maximize the game view on play so you can still see the scene view and inspector, pause the game when a button is on screen and look at where in the scene hirachy the button is, and what its inspector says about its components and parameters


    though also in this case where you keep repeatingly spawning the same type of object over and over again, a prefab as someone mentioned earlier is probably more performant than adding components after instantiation

    for a prefab just drag an object from the scene view in your asset hirachy

    you can then still edit the prefab by double clicking it in the asset hirachy
    that prefab could then already have the component you are adding by script, and can be assigned like a normal gameobject to other scripts without needing to be in the scene already and thus can be instantiated with no prior representation in the scene

    though everything also technically works without prefabs, not-using prefabs is not the problem here
     
    Last edited: May 23, 2021
  22. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    8,188
    If it doesn't change colour, it means it's not underneath a canvas with a graphics raycaster, and thus not seeing raycasts from the mouse.

    And yeah, as suggested, you should really just make the button a prefab with all the necessary scripts already attached/set-up that gets instantiated, rather than adding components at run time.
     
  23. OwenTheProgrammer

    OwenTheProgrammer

    Joined:
    May 19, 2021
    Posts:
    16
    Hi guys

    I think i found the problem but don't know how to solve it or why it says it. Look at the image.
    It says <Missing Tile.TilePressed>

    Does someone know how to solve it??

    Thanks for everyone who wants to help me!

    Kind regards
    Owen
     

    Attached Files:

  24. OwenTheProgrammer

    OwenTheProgrammer

    Joined:
    May 19, 2021
    Posts:
    16
    Hi

    Little Update

    I already changed the <Missing Tile.TilePressed> the problem was because of the prefab

    But it still doesn't work :(

    Kind regards
    Owen
     
  25. OwenTheProgrammer

    OwenTheProgrammer

    Joined:
    May 19, 2021
    Posts:
    16
    Hi

    Another update XD :rolleyes::)

    I solved my problem!!!!! I'm so happy!

    For those who are interested the problem was in my Image, the raycast target was for some reason unchecked instead of checked XD. Oh silly me :D

    Kind regards
    Owen
     

    Attached Files: