Using C# Events with Unity

Discussion in 'Scripting' started by Vimalakirti, Aug 24, 2010.

  1. Vimalakirti

    Vimalakirti

    Member

    Joined:
    Oct 12, 2009
    Messages:
    752
    I am having a hard time figuring out how to use C# events with my Unity scripts. I'm not that experienced.

    What I would like is to be able to trigger an event when I want and have various scripts in various objects receive the message that the event has been triggered to do stuff of their own.

    Could someone post a generic event handler in C# that I can use as a template for my own code please? I'm looking for something like this:

    In one object we have:
    Code (csharp):
    1. // This script triggers the event:
    2. if(GUI.Button (...))
    3.     {
    4.     // trigger event
    5.     }
    In another object we have:
    Code (csharp):
    1. // This script also triggers the same event:
    2. if(Raycast (...))
    3.     {
    4.     // trigger event
    5.     }
    In another object we have:
    // This function gets triggered by the event:
    Code (csharp):
    1. void TriggerEvent()
    2.     {
    3.     // does stuff
    4.     }
    And yet other objects can also be triggered and do their own thing.

    I'm wading through Daniel Solis' book Illustrated C# 2005 which has enabled me to translate my scripts from JS to C#, but for some reason I'm choking on Events.

    Also, do I have to use another "using System." statement?

    Thank you!
     
  2. Eagle32

    Eagle32

    New Member

    Joined:
    Jun 20, 2010
    Messages:
    89
  3. jedy

    jedy

    Member

    Joined:
    Aug 1, 2010
    Messages:
    569
  4. Vimalakirti

    Vimalakirti

    Member

    Joined:
    Oct 12, 2009
    Messages:
    752
    After further struggles I used jedybg's out of the box solution, or rather it's predecessor, CSharpMessenger, from the Wiki here:

    http://www.unifycommunity.com/wiki/index.php?title=CSharpMessenger

    It's just too easy not to use! Perhaps someday when I have more than a week of c# experience under my belt I'll be able to write and use Delegates and Events on my own as needed, but until then this solution will free my time to continue to learn about the basics of object oriented programming.

    Thanks for those links to both of you!!!

    :D
     
  5. DifficultMass

    DifficultMass

    New Member

    Joined:
    Feb 10, 2010
    Messages:
    8
    I don't know whether it's different within Unity (just come back after a long time away and still only exploring this wonderful software.)

    However, events, C# style:


    Code (csharp):
    1.  
    2.  
    3. // Player.cs
    4. namespace PlayerStuff
    5. {
    6.    public delegate void PlayerRespawnedEventHandler(float x, float y);
    7.    
    8.    class Player
    9.    {
    10.        public event PlayerRespawnedEventHandler PlayerHasRespawned;
    11.        private Vec2 m_pos;
    12.  
    13.        public Player(Vec2 pos)
    14.        {
    15.            // Initialise player
    16.            m_pos = pos;
    17.        }
    18.  
    19.        // Lots of player stuff
    20.  
    21.        private PlayerDied()
    22.        {
    23.            // Respawn player
    24.  
    25.            // null check not necessary, but helps
    26.            if(PlayerHasRespawned != null)
    27.            {
    28.               // All listeners will be invoked
    29.               PlayerHasRespawned(m_pos.x, m_pos.y);
    30.            }
    31.        }
    32.    }
    33. }
    34.  
    Then some other file

    Code (csharp):
    1.  
    2. // GameEvents.cs
    3.  
    4. namespace GameStuff
    5. {
    6.     class Status
    7.     {
    8.         // Doing stuff
    9.        
    10.         public Status()
    11.         {
    12.            // Get handle to player game object
    13.            
    14.            // Now hook up to event
    15.            playerGameObject.PlayerHasRespawned += new PlayerRespawnedEventHandler(ActOnRespawn);
    16.         }
    17.  
    18.         private void ActOnRespawn(float x, float y)
    19.         {
    20.             // Do the funky chicken.
    21.         }
    22.     }
    23. ]
    24.  
    25.  

    The event that Player exposes is of type PlayerRespawnedEvenHandler. This defines the data that will be supplied when the event is called. Our GameStff class wants to know when a player has respawned and so after getting a handle to the instance (will be via a Unity API call, I guess) can hook up to the event. It is effectively saying when the event happens, I'll (GameStuff) do some actions that you (Player) don't need to know about. You could also say Player has delegated some work away from itself, but given the paradigm, it's verging on chicken/egg debate. Anywho, the GameStuff tells the event that when it is invoked, it should call the function ActOnRespawn, which as we can see, has the necessary parameters in the function definition.

    So, when the player dies, we'll assume PlayerDied gets called to respawn the player. Within this, it checks to see if anyone cares about the event (not a necessary check, but a good safety) and will invoke the event if necessary. You can think of this as calling a function, as that is pretty much what it is, it just doesn't know if/where these functions are in memory until they are hooked up at runtime.



    In your case, you could simply define the event as an EventHandler, which takes no arguments (and means no need for declaring the delegate) so Player.cs would be:


    Code (csharp):
    1.  
    2. namespace GenericEvents
    3. {  
    4.    class EventTriggerer
    5.    {
    6.        public event EventHandler OurEvent;
    7.  
    8.        public void TriggerEvent()
    9.        {
    10.           if(OurEvent != null)
    11.           {
    12.              OurEvent();
    13.           }
    14.        }
    15.    }
    16.  
    17.    class OtherObject
    18.    {
    19.          private EventTriggerer m_trig;
    20.          public SomeFunction()
    21.          {
    22.               if(GUI.Button)
    23.               {
    24.                    m_trig.TriggerEvent();
    25.               }
    26.          }
    27.    }
    28. }
    29.  

    Every object that was going to trigger the event would need a handle to the object that contained the event to be triggered, but it would enable that event to be triggered by any other given object at any time and so anything that was in turn subscribed to the event OurEvent would be invoked accordingly.

    Hopefully that makes sense. It's late and when you use something every day, it sometimes becomes difficult to explain clearly without going into too much, unnecessary detail.
     
  6. paskal007r

    paskal007r

    Member

    Joined:
    Sep 6, 2013
    Messages:
    12
    I've come here to find out about defining my events in c#, a matter in which I was completely ignorant until last week. This thread was immensely useful, thanks to everyone.

    Digging deeper i also found Advanced CSharp Messenger: http://wiki.unity3d.com/index.php?title=Advanced_CSharp_Messenger
    An updated version of the messenger linked in the above posts.

    Also, here is the link to a discussion where the messenger has been recently updated:
    http://forum.unity3d.com/threads/112449-Advanced-C-Messenger/page2

    Hope it benefits anyone ;)
     
    Last edited: Feb 6, 2014
  7. The.Epix.Code

    The.Epix.Code

    Member

    Joined:
    May 25, 2013
    Messages:
    2
    Hey all!

    That's a really interesting thread!

    I've worked on many video games and events are something really useful if you know how to use them correctly. To put my two cents, I created a library on top of the delegate type of C# combine with my own implementation of WeakDictionary (which doesn't exist natively in the Mono version of Unity). I consider it as a better option than CSharp Manager but I'll let you judge that by yourself!

    You can get it here: https://www.assetstore.unity3d.com/en/#!/content/21467

    Or get more info here: http://www.epixeventspro.com/

    Cheers!
     
  8. cmcpasserby

    cmcpasserby

    Member

    Joined:
    Jul 18, 2014
    Messages:
    145
    just use c# delegates and events.

    you can create events by doing this
    Code (CSharp):
    1. public delegate void EventHandler();
    2. public static event EventHandler onGameActive;
    3. public static event EventHandler onResetAll;
    4.  
    than to trigger them
    Code (CSharp):
    1. if (onGameActive != null)
    2.     onGameActive();
    3.  
    and finally subscribe by doing this in your monobehaviors Start or Awake Method
    Code (CSharp):
    1. Game_System_Logic.onResetAll += this.ResetAll;
    pretty easy and elegant