Author Topic: UIEventListener.Get, delegate coupling best practices?  (Read 6826 times)

hardcoded

  • Guest
UIEventListener.Get, delegate coupling best practices?
« on: April 18, 2012, 07:59:34 PM »
I was wondering what the best(or good) way to handle deregistering delegates from uieventlisteners? 

If I write a simple script like this(and attach it to a gameobject):
  1. void OnEnable () {
  2.         UIEventListener.Get(myButton).onClick = myButtonHandlerDelegate;
  3. }
  4. void OnDisable(){
  5.         UIEventListener.Get(myButton).onClick = null;
  6. }
  7.  
If the UIEventListener object gets cleaned up before this object, then the Get() request ends up throwing an error, since it is accessing a gameobject that has been deleted when the program shuts down. 

So this makes me wonder... What is the right way to wire up game logic to these UIEventListeners?
The options I'm aware of:
   1) wire up a listener to a custom OnClick() handler that is on the same game object that would
   2) don't deregester, not a great option in many cases
   3) cache the monobehaviour
   4) ???

What is the best practices that you use or is there a hard and fast "right" way to couple game logic to buttons using ngui, while still making sure to register/deregester delegates?
« Last Edit: April 18, 2012, 08:04:24 PM by hardcoded »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: UIEventListener.Get, delegate coupling best practices?
« Reply #1 on: April 18, 2012, 08:25:29 PM »
You can always just use GetComponent to determine if UIEventListener is there or not:

  1. UIEventListener listener = myButton.GetComponent<UIEventListener>();
  2. if (listener != null) listener.onClick -= myButtonHandlerDelegate;

I also suggest using "+=" instead of "=" to assign the delegate. This way you can have more than one listener tied into the same object:

  1. UIEventListener.Get(myButton).onClick += myButtonHandlerDelegate;

hardcoded

  • Guest
Re: UIEventListener.Get, delegate coupling best practices?
« Reply #2 on: April 19, 2012, 11:50:17 AM »
GetComponent() is actually what fails here. (inside of UIEventListener.Get)  The period of time between Destroy() and having an invalid GameObject reference is the issue.

When calling GetComponent on an object that has been destroyed, but not yet garbage collected. When you call Destroy() in update, and I think it's garbage collected in lateupdate, the editor complains and the iphone crashes.  This is bad if you are spinning up objects, or during the end of the game.  Player data serialization can fail to execute if this sort of crash happens at the end of the game, or the game can crash if it happens during execution.

This means that if I had the UIEventListener cached, it would probably not fail, but GetComponent() or by extension UIEventListener.Get(), do fail.  Thus I was wondering the best way to structure my code handlers given that.

I think I still have the sample that fails if you need to have a more concrete example.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: UIEventListener.Get, delegate coupling best practices?
« Reply #3 on: April 19, 2012, 11:52:33 AM »
Try changing the != comparison to just if(listener). Just doing a straight boolean eval on a monobehavior is supposed to check it against null as well as the destroyed object queue.

hardcoded

  • Guest
Re: UIEventListener.Get, delegate coupling best practices?
« Reply #4 on: April 19, 2012, 03:34:25 PM »
I'll be damned!  Brilliant.  Worked like a charm.  I can't believe I never ran across that tip before :) 

Thanks a ton!

Maxii

  • Jr. Member
  • **
  • Thank You
  • -Given: 4
  • -Receive: 0
  • Posts: 55
    • View Profile
    • Strategic Forge
Re: UIEventListener.Get, delegate coupling best practices?
« Reply #5 on: August 20, 2013, 09:45:48 AM »
Quote
Just doing a straight boolean eval on a monobehavior is supposed to check it against null as well as the destroyed object queue.

Aren, have you been able to verify the above? My testing seems to indicate that a monobehaviour and/or game object slated for destruction but not yet null returns true. It sure would be helpful if it were true!
I'm looking for an artist partner to complement my programming skill in developing a space-based Civilization-like empire building game, ala GalCiv2 or Distant Worlds based on Unity3D.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: UIEventListener.Get, delegate coupling best practices?
« Reply #6 on: August 20, 2013, 02:08:52 PM »
That's how it has always been as far as I know (should return 'false', I mean). *shrug*

If you're getting a 'true' even though you called Destroy(go), then maybe it changed at some point?