Getting return value of UnityEvent?

Is there a way to get the return values of UnityEvent? Specifically, I want to get the return value if it is Task.

This is what I would like to do: I want to implement a generalized mission pipeline so that the sequence of function calls are data-fied. I will add function calls in the inspector and they will be called in sequence. Some of the functions are async though, so I want to await them before the next call. Of course, the order of execution matters.

In pseudo code it looks something like this:

public class CustomEvent : UnityEvent{};
public CustomEvent OnEvent;

public async void CallOnEvent()
{
    foreach(var event in OnEvent)    //How do I iterate through all events?
    {
        Object result = event();            //How do I get the return value of each event as Object?
        Task resultT = result as Task;
        if(resultT!=null) await resultT;
    }
}

Is this possible with UnityEvent? Or is there a way to write a new class that can be edited similar to UnityEvent and can have each function awaited?

I wouldn’t try to use UnityEvent for this. They’re intended to be Fire and Forget.

Any reason you can’t just use a custom delegate type or even just System.Func<Task>?

My main goal is to have my function calls editable in inspector, thus making it data instead of code. I don’t know how to edit delegates from inspector. Or maybe there’s a way to make a wrapper class that does that?

Also, frankly I’ve been using delegates as fire-and-forget as well. Could you point me to the docs on how to get delegate return values?

You want to return a value and control (delay) the call of the event handlers, neither of these is possible with the default UnityEvent unless you butcher it to a point where it would not make sense to use it anymore.

I don’t think there is any built-in way to serialize delegates (other than UnityEvents) so you would have to write your own class for this, you would have to store a reference to a Unity scene target object / component and the method name (string) you want to invoke at runtime. You have to store the name of the method, because you can’t serialize the method itself in the inspector.

So you need a small class to to store these informations and store them in a list, then you could write your custom inspector to make it easier to use, for example show a dropdown of possible methods on the current target object instead of typing the method name in a text box etc.

At runtime you would “prepare” the event by using reflection to get the actual callback method by name on the target object / component just once so that you can call it later.

The UnityEvents are implemented in a similar way btw.

Then you have full control of which delegates you want to use and how they should be invoked and how they return value should be used etc.

But before you do any of this you should research, because I would assume that someone else already wrote a similar solution so maybe you can just use their implementation. Maybe the Odin inspector can serialize delgates?

Also keep in mind that multicast delegates can execute multiple subscribed methods at once, but you only have one return value. So you only get the return value of one of the subscribed methods. For this behaviour it’s usually better to use the strategy pattern (i.e. using an interface or abstract / virtual base class).

Odin User here. I’d never tried this, but turns out you can!7447088--913238--upload_2021-8-25_18-44-57.png

Little awkward to use. You need to drag a scene object, asset or script into the target on the right side, and then select a method with a matching signature with the drop down.

Also found that SerializeReference while using Unity’s serialisation doesn’t cause the field to be saved in any manner, even though it’s exposed. However using Odin’s intermediary classes that use their serialisation (eg: SerializedScriptableObject) does cause the fields to both be exposed and saved with SerializeField.

Interesting stuff to know.

Edit: I’ll add that I didn’t do any testing beyond this to see how it works at runtime, etc. I did just noticed that the fields are cleared after opening and closing unity, but the asset (an SO in this case) still had the data stored under the hood.

1 Like

Seems a lot more complecated than I imagined. I’ll take a look at Odin inspector. Thank you!

Also, one other reason that I use UnityEvent is that it accepts functions with various signatures, and I do need to call functions with various signatures. Is that possible with delegates?