Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Nanako · Apr 20, 2015 at 11:56 AM · eventlistener

How do i declare an event listener?

Ok, two seperate classes.

First of all, there's my SelectionManager class, it governs selecting of units (isometric/topdown game) and i want it to fire off an event whenever the selection changes.

I'm using this to define the event:

 public delegate void SelectionEventHandler(GameObject justSelected);
     public event SelectionEventHandler SelectionChanged;


And i'm using this line to fire off an event

 SelectionChanged(active);


This compiles without errors, but i've not been able to test it.

Secondly, the other class, this one is named FixedCamera It contains a reference to the instance of my SelectionManager class (the reference variable is named "selectionManager")

I'm attempting to define a listener on the aforementioned event, like this:

 selectionManager.SelectionChanged += new SelectionEventHandler(SetSubject);

However this won't compile, SelectionEventHandler has a red underline. The tooltip error is: "The type or namespace "SelectionEventHandler" could not be found..."

My obvious first thought then, is that it doesn't know where to look, so i tried this

 selectionManager.SelectionChanged += new selectionManager.SelectionEventHandler(SetSubject);


However this throws a different error "selectionManager is a field, but is used like a type"

I'm stumped. What am i not getting?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Xarbrough · Apr 20, 2015 at 12:06 PM

Try this:

 //class SelectionManager
 public delegate void SelectionEvent (GameObject selected);
 public static event SelectionEvent OnSelectionChanged;
 
 //class Listener
 SelectionManager.OnSelectionChanged += HandleNewSelection;
 
 void HandleNewSelection(GameObject selected) {
     //
 }


You're event should be static, so that it is available everywhere. Next you can just assign a method to your delegate.

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image CHPedersen · Apr 20, 2015 at 12:33 PM 0
Share

It most certainly does not need to be static. Example co$$anonymous$$g up.

Edit: Done writing example. :) See my answer. To clarify my response to this: If you make the event static, then you're detaching it from the objects which are instances of the class. It becomes common for them all. This could be useful, I suppose, if all the class's instances should all share the same handler for that event. But there are tons and tons of use cases for events where that is not at all what you want. Imagine, for example, if the event handler for a GUI button was static. Then all buttons across your entire GUI would do the same thing when you clicked them. :)

avatar image Xarbrough · Apr 20, 2015 at 12:53 PM 0
Share

Valid point. $$anonymous$$y argument for static events is that in this case it works like a "global" event that only fires for a single action, namely the selection of the current unit. In a global manager with only a few events, this is a nice and easy approach. For everything else I would go with CHPedersen's approach.

avatar image CHPedersen · Apr 20, 2015 at 01:05 PM 0
Share

That's fair enough. :) (downvote removed). Though, the typical approach to object selection is to have e.g. OnSelected events associated with the object instances rather than a global manager. Just like something like "On$$anonymous$$ouseEnter" is associated with each instance of $$anonymous$$onoBehaviour. But one could argue that concerns the pattern OP followed rather than his issue with calling syntax, so your answer is correct.

avatar image Bunny83 · Apr 20, 2015 at 02:21 PM 0
Share

Just want to add that "SelectionEventHandler" is a nested-type. So if you want to use it outside the Selection$$anonymous$$anager scope you have to use the "class name" to get the inner class.

 selection$$anonymous$$anager.SelectionChanged += new Selection$$anonymous$$anager.SelectionEventHandler(SetSubject);

Note the upper case "S" so we use the class, not the reference to the instance. You never use an instance reference when you want to access a type.

Type definitions are "static stuff", so to access a nested type (enum, class, delegate, struct, ...) use the classname of the outer class followed by the nested classname seperated with a dot.

See the last paragraph over here

Another solution is to define your delegate type outside of your Selection$$anonymous$$anager class so the type will be part of the current namespace scope. You should only nest types if they are truly only used in combination of the outer class. So when it's a type that comes with that class and is only ment to be used with that class.

If it's a more general type definition it should not be a nested type.

avatar image
1

Answer by CHPedersen · Apr 20, 2015 at 12:38 PM

What you have is almost correct. I have an event declared like below. Disregard that its name has data and buffers and what not in them, that's because it's actual code I just copy-pasted from a project. At later stages, I will replace the EventArgs with a custom class that holds my own event arguments, of course. But this demonstrates the pattern, at least.

 public delegate void DataProcessedDelegate(object sender, EventArgs e);
 public event DataProcessedDelegate OnDataProcessed;

I fire it the same way you do, except that you should check it against null first. An event is null if it has no listeners attached:

         if (OnDataProcessed != null)
             OnDataProcessed(this, new EventArgs());

A listener (event handler) is attached like so:

     WRSProcBuffer buffer = new WRSProcBuffer(2048); // Irrelevant, this is just for the sake of the example
     buffer.OnDataProcessed += buffer_OnDataProcessed;

Where the handler itself is a method with a signature that matches the arguments declared in the delegate:

 void buffer_OnDataProcessed(object sender, EventArgs e)
 {
     // Triggered when the event is raised
 }
Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Nanako · Apr 20, 2015 at 02:39 PM 0
Share

What do you mean an event is null if it has no listeners? will it throw an error, or is that just a performance consideration?

i don't understand what you're doing with the attaching a listener, and how it differs from my example. what is WRSProcBuffer?

avatar image CHPedersen · Apr 20, 2015 at 03:10 PM 0
Share

I mean it is null, as in, it will throw a NullReferenceException if you attempt to raise an event that has no listeners. As for WRSProcBuffer, forget about that. That's just a classname specific to my project only. It's here because this example comes from actual code in my project. I explained that in the beginning of this reply. :-)

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

21 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Why UI event handlers dont get memory leaks if listener not removed 1 Answer

Game Object not self destroying after Destroy(gameObject) 3 Answers

How do i declare a non-static event? 1 Answer

Notifying multiple enemies on player death 0 Answers

GameObject.Find breaks code with UnityEvent 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges