- Home /
AddListener function not working?
I'm trying to add an event to a procedurally generated button, using the following script;
Transform purchaseButton = newItem.transform.FindChild("Purchase");
if (purchaseButton != null) {
Debug.Log("found button");
purchaseButton.GetComponent<Button>().onClick.AddListener(delegate {btnClicked("testarg"); });
}
public void btnClicked(String param) {
Debug.Log ("button clicked: " + param);
}
Unfortunately, it looks like this isn't being updated at all in the game object - clicking into it via the unity interface doesn't show any update on the button function, nor does the button itself call the method I've passed through via the AddListener function.
Can anyone lend me a hand with this?
Note: using the answer here will still not update in the gui as the listeners added in scripts are of a different type to those added from the gui (non-persistent rather than persistent)
I did actually read through that - that's where I got the above script from. I can't see where it's going wrong - and I'm not being returned any errors or the likes.
The script is set up to generate all these buttons as child objects; I then run through them to change the text to match the intended button action (works perfectly), but actually attaching an OnClick to the button itself seems to be where everything is falling apart. As you can see above, I'm just trying to test it with a very basic Debug.Log action.. and am unfortunately, not getting any output.
Have you tried doing it in the lambda expression way as shown on that question as opposed to how you have done it above?
AddListener(() => { btnClicked("testarg"); });
Did you ever figure this out? I'm running into a similar issue and it looks kind of like a race condition.
I have encountered the same problem. I tried UnityEvent and System.Action, but both fail to register, when they are on an instantiated prefab.
I use nearly identical code on other objects, that are placed in the scene by hand, and there it works.
Answer by HedgeWizard137 · Apr 07, 2017 at 06:28 AM
Here is what I did. I had a prefab button I want to Instantiate and then addListener, but what I did was add the listener to the prefab and not to the clone I just Instantiated.
public GameObject prefab; //prefab you want to Instantiate
public GameObject obj; //the Instantiated clone
void Start(){
obj = Instantiate(prefab, parent)
obj.GetComponent<Button>().onClick.AddListener((delegate { yourMethod();)); //or the lambda way (() => {yourMethod();})
//mistake I made
prefab.GetComponent<Button>().onClick.AddListener(delegate stuff) //this is what caused my problem.
}
I got to fancy with naming variables and should have used simpler names like obj and prefab.
Answer by wowipop · Dec 26, 2014 at 04:35 AM
Transform purchaseButton = newItem.transform.FindChild("Purchase");
if (purchaseButton != null) {
Debug.Log("found button");
UnityEngine.Events.UnityAction action1 = () => { this.btnClicked("testarg"); };
purchaseButton.GetComponent<Button>().onClick.AddListener(action1);
}
public void btnClicked(String param) {
Debug.Log ("button clicked: " + param);
}
This will not be displayed on editor but still works
Unfortunately, this didn't work either. No compile/runtime errors or anything; the buttons just aren't doing anything when clicked. Any other ideas?
Answer by Drakoran · Feb 20, 2016 at 10:20 AM
I also ran into this issue. Somehow, I unchecked the Raycast target on the image script. Checking this allowed the onClick.AddListener() to work.
.onClick.AddListener(() => TestAddition());
private void TestAddition() { Debug.Log("Testing Button"); }
This doesn't work still if you do GetComponent(Button) I already have Raycast checked on the image script
Answer by erofes · Sep 03, 2018 at 01:23 PM
Hi there!
I have one solution for someone who encounters the same sort of the problem.
If you want to create Prefab of game object, which will contain button or buttons as components of parent itself, or inside of his childrens, and you want to initiate it's Listeners with onClick = () => { someDelegate}; And then instantiate them and catch their Listeners all finely working.
Just add this method: GameObject InstantiateWithListeners
GameObject InstantiateWithListeners(GameObject prefab, Transform parentTransform)
{
GameObject instance = GameObject.Instantiate(prefab, parentTransform) as GameObject;
if (instance.GetComponent<Button>() != null)
instance.GetComponent<Button>().onClick = prefab.GetComponent<Button>().onClick;
}
And use it instead of usual GameObject.Instantiate(); So now you can use:
GameObject m_somePrefab;
Transform m_parentTransform;
void Start()
{
m_somePrefab.GetComponent<Button>().onClick = () => { Debug.Log("Hello there!"); };
}
GameObject InstantiateSomePrefab()
{
GameObject instance = InstantiateWithListeners(m_somePrefab, m_parentTransform) as GameObject;
return instance;
}
By the way, to get Button component in child or set a bunch of buttons, I will recommend you to create simple MonoBehaviour component on parent game object and add to him public List of Buttons. After that, Initiate this prefab with all needed button components in inspector. Now you can easily iterate on every matching Button component inside InstantiateWithListeners method and initiate it with proper Listener as was shown above.
Answer by misher · Sep 03, 2018 at 01:44 PM
First, don't use Transform.FinsChild, it is deprecdated, you can look straight for a button component in a child. Second, use simple lambda function if you want to pass a parameter to other methos.
...
Button purchaseButton = newItem.GetComponentInChildren<Button>();
if (purchaseButton != null)
{
Debug.Log("found button");
purchaseButton.onClick.AddListener(() =>
{
BtnClicked("testarg");
});
}
...
public void BtnClicked(string param)
{
Debug.Log("button clicked: " + param);
}