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. Dismiss Notice

Button.onClick headache when trying to Add a listerer in a component of a prefab.

Discussion in 'UGUI & TextMesh Pro' started by TheLurkingDev, Sep 3, 2014.

  1. TheLurkingDev

    TheLurkingDev

    Joined:
    Nov 16, 2009
    Posts:
    91
    I have a button prefab that I am instantiating at runtime and I am trying to be notified of the Unity button's onClick() event. After consulting the forums and making a few different attempts, here is my last effort:

    Code (CSharp):
    1. void Start()
    2.     {
    3.         Button btn = gameObject.GetComponent<Button>();
    4.         btn.onClick.AddListener(delegate { OnButtonClick(); });        
    5.     }
    6.  
    7. public void OnButtonClick()
    8.     {
    9.         _justClicked = true;
    10.         PostEventNotification(EVENT_TYPE.OnGameSpriteTextureClick);
    11.     }
    I am still receiving the exact same error:
     
  2. Senshi

    Senshi

    Joined:
    Oct 3, 2010
    Posts:
    556
    Yeah, that error isn't very descriptive and, if you're using an earlier beta, is missing the correct stack trace. The most common cause I've seen here is that something, *somewhere* is null.
     
  3. TheLurkingDev

    TheLurkingDev

    Joined:
    Nov 16, 2009
    Posts:
    91
    I'm using b17. b18 is out but not fully tested. Your answer narrowed it down, but thanks for the response. :)
     
  4. TheLurkingDev

    TheLurkingDev

    Joined:
    Nov 16, 2009
    Posts:
    91
    I have tried dragging the component of the prefab into the OnClick event field in the Inspector and also leaving it empty in conjunction with the code shown above. Is there something else maybe I can try?
     
  5. Senshi

    Senshi

    Joined:
    Oct 3, 2010
    Posts:
    556
    I believe that particular snippet should work without an EventTrigger due to onClick being a Button property, but don't quote me on that. What exactly isn't working? Are you still getting errors?
     
  6. TheLurkingDev

    TheLurkingDev

    Joined:
    Nov 16, 2009
    Posts:
    91
    Yes, it is still not working. Same error and same description as above. It doesn't change no matter what I put into the onClick method in the Inspector.
     
  7. Senshi

    Senshi

    Joined:
    Oct 3, 2010
    Posts:
    556
    Ok, so two first steps to fixing this puppy then:

    1) Remove either the code to add a Listener to onClick, or remove it from the editor list. Let's keep this problem as basic as possible, without redundanicies. =)

    2) Figure out where that error is coming from; it could be anywhere. Does it only happen when you click the button? If so, try commenting your method's body line by line to try and find the cause. If not, do null checks elsewhere. Is `btn` assigned to properly? Was the Component perhaps not found? Stuff like that.
     
  8. orb

    orb

    Joined:
    Nov 24, 2010
    Posts:
    3,033
    This is a minimal component for adding to a button or other canvas element that needs to respond to a click event:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.EventSystems;
    3.  
    4. public class Click : MonoBehaviour, IPointerClickHandler
    5. {
    6.     public void OnPointerClick(PointerEventData data)
    7.     {
    8.         Debug.Log("Clicked at "+data.position.x+","+data.position.y);
    9.     }
    10. }
     
    TheLurkingDev likes this.
  9. Tim-C

    Tim-C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Posts:
    2,181
    Whats the full error in the log? There should be a stacktrace there that points to the line the error is happening on (it is a nested exception).
     
  10. TheLurkingDev

    TheLurkingDev

    Joined:
    Nov 16, 2009
    Posts:
    91
    This is all I see:
     
  11. TheLurkingDev

    TheLurkingDev

    Joined:
    Nov 16, 2009
    Posts:
    91
    First of all, thanks again for you help.

    There appears to be something wrong elsewhere, external to my code file. The same error also occurs when I comment out my code and then manually add the component/method to the OnClick specification of the Button component of my prefab and then apply it to the prefab.
     
    Senshi likes this.
  12. TheLurkingDev

    TheLurkingDev

    Joined:
    Nov 16, 2009
    Posts:
    91
    Excellent, thank you very much! This solved the problem.
     
    Senshi likes this.
  13. TheLurkingDev

    TheLurkingDev

    Joined:
    Nov 16, 2009
    Posts:
    91
    Ok, I was absolutely wrong and it is time for me to eat crow. It is my code causing the problem. I must have had it commented out when I thought everything was working above. It appears that by hooking into the OnClick event for the button has hijacked my own event handling system that was previously working. Specifically, in my NotificationsManager class, I am maintaining a list of IListener objects. When I need to post a notification to those listeners, I am passing in the event type that is being listened for and then using reflection to invoke the method on the listener that matches the event type.

    Here is the PostEventNotification() method from my NotificationsManager:
    Code (CSharp):
    1. public void PostEventNotification(EVENT_TYPE Event_Type)
    2.     {
    3.         if(!_listeners.ContainsKey(Event_Type.ToString()))
    4.             return;
    5.  
    6.         // Notify all listeners.
    7.         foreach(IListener thisListener in _listeners[Event_Type.ToString()])
    8.         {
    9.             // Use Reflection to make the method call matching the EventType.
    10.             Type type = thisListener.GetType();
    11.             Debug.Log("Listener type: " + thisListener.GetType());
    12.             MethodInfo method = type.GetMethod(Event_Type.ToString());
    13.             Debug.Log("method.Name: " + method.Name);
    14.             //method.Invoke(thisListener, null);
    15.         }

    The very last line that is commented out is where the error occurs. When I call the Invoke method on the MethodInfo instance I receive this:
    So first, my apologies to all of you for leading you on a wild goose chase. However, now that I finally seem to be on the right track to solving this, I still do not understand why IPointerClickHandler is expected. TextureButton is what is sent and that is what it should be, at least that was the way it was working before tying into Unity's events.

    Relevant to this is probably the code that is run when I initially add the TextureButton object as a listener.

    Code (CSharp):
    1. private Dictionary<string, List<IListener>> _listeners = new Dictionary<string, List<IListener>>();
    2.  
    3.     public void AddListener(IListener listenerObject, string EventName)
    4.     {
    5.         // Create new List within Dictionary representing the EventType if not already there.
    6.         if(!_listeners.ContainsKey(EventName))
    7.             _listeners.Add(EventName, new List<IListener>());
    8.  
    9.         // Add the listener to the correct List.
    10.         _listeners[EventName].Add(listenerObject);
    11.     }
    And the call to AddListener() from the TextureButton class:
    Code (CSharp):
    1. public void AddListener ()
    2.     {
    3.         GameManagerInstance.NotificationsMgr.AddListener(this, EVENT_TYPE.OnGameSpriteTextureClick.ToString());
    4.     }
     
  14. TheLurkingDev

    TheLurkingDev

    Joined:
    Nov 16, 2009
    Posts:
    91
    To finally solve the problem, I scrapped using reflection in .NET and decided to use it in Unity via the GameObject.SendMessage() method. So for anyone who might be interestedin the final resolution (though I don't know why since it is completely off-topic now), here is the rewrite of the PostEventNotfification method:

    Code (CSharp):
    1. public void PostEventNotification(EVENT_TYPE Event_Type)
    2.     {
    3.         if(!_listeners.ContainsKey(Event_Type.ToString()))
    4.             return;
    5.  
    6.         // Notify all listeners.
    7.         foreach(IListener thisListener in _listeners[Event_Type.ToString()])
    8.         {
    9.             TextureButton thisButton = thisListener as TextureButton;
    10.             thisButton.SendMessage(Event_Type.ToString(), thisListener, SendMessageOptions.DontRequireReceiver);
    11.         }
    12.     }
     
  15. Tim-C

    Tim-C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Posts:
    2,181
    Just a question, are you sure that is the full log? There should be a details panel (the bottom part of the console) that has a stack trace. There should always be more information there then what you have pasted here.

    Attached is a pic of a button that causes a null ref on Beta 18.
    Screen Shot 2014-09-05 at 11.09.31 am.png
     
  16. TheLurkingDev

    TheLurkingDev

    Joined:
    Nov 16, 2009
    Posts:
    91
    Positive there was nothing else. I even triggered the exception in normal mode and in debug mode, but it did not change. What I copied and pasted here was all that appeared in the console. It actually looks identical in the upper portion of the console except it has the red icon and is not selectable whereas in the bottom part it is selectable.

    I have already stripped out the offending code, but if you like I will replace it and grab a screen shot.
     
  17. Venged

    Venged

    Joined:
    Oct 24, 2010
    Posts:
    500
    Would this work for a New Unity GUI Slider. I can control morp Targets with the Legacy GUI Sliders and with NGUI but canit find how to use the New Gui.

    Is there a OnSlider.....( ) ?

    Thanks
     
  18. TheLurkingDev

    TheLurkingDev

    Joined:
    Nov 16, 2009
    Posts:
    91
    I can see that there is a OnScrollEvent subclass of the Slider class. Seeing this, I would suspect that there is an OnScroll() that you could hook into. However, I have not attempted with any uGUI 2 events other than the OnClick() detailed above.
     
    Venged likes this.
  19. Venged

    Venged

    Joined:
    Oct 24, 2010
    Posts:
    500
    Thanks