However, in psuedocode I can definitely see an issue of not knowing which event listeners have been placed in a complex class that may or may not add certain listeners. Apparently you can’t just un-listen from them, as it throws exceptions, and even if it didn’t crash it’d just be bad practice. Is there a way to check if an event listener has actually been added before removing it?
I will not answer the question using the c# messenger system but use the c# events because unity supports it as StarManta pointed out(you can also use UnityEvents). Issues with subscribing and unsubscribing usually occur when you persist singletons with listeners across scenes and fill it with references to objects of different levels without unsubscribing from them when scenes are changed. So if a callback uses or alters an object that was destroyed wu=ith the previous scene there would be issues. So in case of inability to track listeners a good hack would be to set up an event Manager which is basically a class that has an event with a pointer and that obviously should be invocable somewhere and un-subscribe from them as shown below. The shortcut to preventing exceptions would be to use the catch blocks still.
void OnEnable()
{
SceneManager.sceneLoaded += OnSceneLoaded;
try{
EventManager.EventName1 += CallbackName;
}
catch{
Debug.log("Event already subscribed to or does not exist@ EvetName1");
}
try{
EventManager.EventName2 += callbackName;
}
catch{
Debug.log("Event already subscribed to ordoes not exist @ EvetName2");
}
void OnSceneLoaded(
Scene scene, LoadScenemode
)
{
//if this object will persist across scenes, you can remove listeners here also depending on the scene you are in
}
void OnDisable() //usubscribe from each event
{
SceneManager.sceneLoaded -= OnSceneLoaded;
try{
EventManager.EventName1 -= CallbackName;
}
catch{
Debug.log("You were not subscribed to the event before trying un-subscribe. You should be subscribed to this event@ EventName1 before attempting to un-subscribe");
}
try{
EventManager.EventName2 -= CallbackName;
}
catch{
Debug.log("You were not subscribed to the event before trying un-subscribe. You should be subscribed to this event@ EventName2 before attempting to un-subscribe");
}
}
I’m struggling to figure out why you’d want to use that class over C#'s included “delegate” and “event” keywords. I would’ve assumed the answer was just “because Unity didn’t support that version of C# yet”, but you’re apparently using it in 2019, so may I ask why? Does this script actually have benefits over the delegate/event keywords, or are you unaware of those keywords?
Honestly, as a rule of thumb, anything on wiki.unity3d.com is going to be so outdated as to be worse than useless. The wiki is thoroughly unmaintained, and I’ve made the case before that it’s doing more harm than good and should be shut down/archived. Note that the last time the front page was updated was in 2012, and that was to note a change in policy to combat spambots… which even 7 years ago already constituted the majority of activity on the wiki.
That was a hell of a necro post. Anyway. Note that you can iterate over a multicast delegate. I use this to call each delegate separately in a try. If it catches an exception the offending delegate can be removed and logged for inspection. If this really makes your messaging system failsafe is debateable. But its a start.
I’d have to use the excuse that this is one of my early days of forming the habit of answering questions while being a beginner myself. Iteration would definitely be less painstaking and easier to maintain for a surmountable amount of delegates and just catching exceptions probably isn’t the best solution to this question either.
Your code catches exceptions as well. Where you use them to check wether a delegate has already been added I use them to check wich ones can be removed because their object is gone. Albeit this was not the original question it may help in the mentioned scenario. Iteration could also be usefull to check if a multicast delegate contains a certain object before adding or removing it. Albeit I’m not sure if equality comparison works for delegates it could be worth a try if you need this functionality.