In my app, I was trying to get an object to be active within the function that is attached to a c# event (e.g. via +=). However, the code would not execute when the event was fired. I checked and the function was being called in response to the event, but the set active code was either not executing, or the function did not proceed beyond the set active line. (The actual object is assigned in the editor and actually works when being referenced outside of the event.) Then I decided to set a flag for it in the function that responds to the C# event, and have another function (via Update) evaluate the flag and set the object active. That worked.
My question is why is that the case? Should some types of code not be called in C# Events in unity?
What was causing the event to fire? Most of the stuff in the UnityEngine namespace is only safe to call from the main Unity thread, so if the event was triggering on some other thread, that would cause problems. (It doesnât matter whether or not the function is being called through an event, only what thread its running on. Itâs totally fine to use events as long as those events are only triggered by the main thread.)
Also, you can get issues if you SetActive(true) and SetActive(false) on the same object in the same frame. Intuitively, youâd expect whichever one you did last to âwinâ, but this isnât necessarily the case, because SetActive actually defers some of its effects until later in the frame.
I see. However, when I created the event, I did not fire it from a different thread. I donât specify any thread. Perhaps it was being set twice in the same frame.
It doesnât matter what thread it is created from, it matters what thread it is invoked from.
If your event is named MyEvent, then somewhere you have some code that says MyEvent() or MyEvent.Invoke(), which is what causes the event to run. Whatever thread is executing that line of code also executes the event. (Same rules as any other function or delegateâit inherits the same thread as the caller unless you do something special to ensure otherwise.)
Normally a Unity game wonât involve more than one thread unless you explicitly create a new thread, so unless you are intentionally being multi-threaded Iâd be kinda surprised if this is your problem.
I see. So it must be the conflicting calls since I am not intentionally mulit-threading anything - primarily because I donât even know how to do such. When I use the method of setting a flag that is checked in update, it seems to work. Itâs likely, give what you said, my design probably is attempting to set the objects as active more than once in a frame. Itâs not readily apparent where, because I checked.
Also, this is my first time using an event-driven approach as opposed to grabbing references to objects via GetComponent. So, I will clean those up as I continue.
If thereâs no multithreading involved Iâm at a loss to add anything to this conversation without seeing some of the code in question, ideally marking which code you believe should be executing but is not.
Where do you add the callback to the event?
Where do you invoke the event?
Which code in the callback is not being executed?
Unityâs concept of active/deactivated objects shouldnât have any bearing on the way C# events execute except that if the event is fired within some function that Unity doesnât invoke due to the object not being active, obviously the event wonât be fired.
Thanks. I think it is likely due to conflicting calls. Thankfully, I do think I have enough information based on what was shared in this thread to proceed and resolve the issue. If not, I will post some additional information.
Necro with the solution that fixed this problem for me. I was trying to have my interaction system script subscribe to an event that my dialogue system would fire when the dialogue box was closed. The problem was a classic issue Iâve run into with grabbing other scriptsâ components on awake - the script execution order. I had the dialogue system script in the manual execution order, but not the interaction system script. So, when the interaction system tried to subscribe to the dialogue systemâs event OnEnable, it couldnât, because the dialogue system script wasnât awake yet. I manually told the interaction system script to wake up after the dialogue system script, and boom. Now the event is running perfectly!
I wish Unity would return an error when it doesnât successfully subscribe to an event OnEnable, it wouldâve saved me a day of headaches. But, Iâm aware thatâs easier said than done because of the nature of how events work. Iâm on 2019.4.17f1, not sure if itâs been fixed in newer editor versions. Hope that helps someone!