- Home /
Implementing Unity's Callback System
Hi all, I'm working on a Networking Library for Unity, I need to implement callbacks, or "messages" as the Unity doc calls them, such as OnConnectedToServer(), OnPlayerConnected(), etc, but I don't know how to go about doing it. I've used delegates and interfaces before, but I can't figure out how they work to create these callbacks that are built into MonoBehaviour. If anyone can provide insight or further reading it would be much appreciated. Thanks!!
Answer by Arder Blackard · Oct 02, 2014 at 11:10 AM
You can use the Reflection. The straightforward example can look like following.
class ConnectionData
{
// Some hypothetical data to be passed to the event with paramater
}
class Manager
{
List<System.Object> _listeners = new List<object>();
public void AddListener( System.Object listener )
{
if ( listener != null )
_listeners.Add( listener );
}
public void SendConnectedToServerMessages( ConnectionData data )
{
// Search non-static methods both public and non-public
BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
// Parameters of the method to search for
Type[] paramTypes = { typeof( ConnectionData ) };
// Parameter value to be passed to the method
System.Object[] paramValues = { data };
foreach ( System.Object obj in _listeners )
{
// Search for the method with signature OnConnectedToServer( ConnectionData )
MethodInfo methodInfo = obj.GetType()
.GetMethod( "OnConnectedToServer", flags, null, paramTypes, null );
// Call the method with parameters
if ( methodInfo != null)
methodInfo.Invoke( obj, paramValues );
}
}
}
Manager
stores links to the objects that should accept the events in _listeners
list, and then upon calling the SendConnectedToServerMessages()
searches through all the listeners, and if they have appropriate method - calls them with given parameters (if the listener has no such a method - nothing will be done). Of course it is just a sample, more optimization would be nice to have (like precaching the MethodInfo structures) but this is the point to start from.
http://msdn.microsoft.com/en-us/library/ms173183.aspx - this is the starting page for the Reflection topics on MSDN
Thank you! Don't know that I ever would have stumbled upon reflection based on how I was searching.
So, if I'm understanding your code correctly, I'd call AddListener from every script that had a ConnectedToServer method in order to register it with the manager?
With this approach you can have in the manager a number of methods like SendConnectedToServer$$anonymous$$essages(), SendPlayerConnected$$anonymous$$essages() and so on (lets call them event-emitting methods). Then objects which want to process all or some of these events (listeners) should implement the appropriate methods and register themselves within the $$anonymous$$anager by calling AddListener() (some unregister or cleanup routine to remove the destroyed objects may be needed too). When implemented like this, the listeners are not required to be the child of some common class, implement any interface - they just need to have some methods with correct signatures declared (much like Update(), Start(), OnEnable()... in $$anonymous$$onoBehaviour). Then upon emitting the certain event for each listener if it has an expected method - it will be called, if not - the object will not receive the message (again like the $$anonymous$$onoBehaviour descendants). I'm pretty sure that Unity maintains some kind of global list of all $$anonymous$$onoBehaviours which acts like the proposed $$anonymous$$anager.
BTW Reflection can give you in runtime the detailed information about any type, class, variable, method and so on (even those that are private and are not accessible otherwise) alowing to explore unknown objects, call their methods, change fields values - sometimes it may be handy (of course there can be some performance drawback for this but using it wisely can help a lot).
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
C# inheritance advice 2 Answers
Changing anchor positions on UI? 0 Answers