Execute method from unknown script set as variable in inspector

The question might seem weird to you, but I had a very specific problem, and this is what I was searching for.

The reason I am making this post is because I was looking for something, and I knew what I wanted, but I had no idea how to look for it. My hope is that with this post I can help someone else out if they have a similar issue.

My issue:
While making a Quest System that was built in the Inspector (no Node-Based system, all configuring is done in the inspector) I realized very quickly that I needed a way for the Quest to call a method to help progress the quest along, and to set unknown variables for things like health (and other stats), armor, and various other things… However, as each quest is made of vastly different parts, I didn’t want to hard-code the method calls as that would defeat the purpose of having a Quest-Building-System.

Here’s how my Quest system works, and why I needed something like this.

My main class Quest is a Serializable class that holds data about a specific part of a quest (i.e: a Quest = one part of an interaction)

Here’s what my Quest.cs looks like:

[System.Serializable]
public class Quest
{
    [Tooltip("If this is a child of another Quest.")]
    public bool isChild = false;
        
    [Tooltip("The id/name of the quest. (Used for look-ups. Should be unique.)")]
    public string name;
        
    [Tooltip("The Text for this object. This is the dialogue presented to the player.")]
    [TextArea]
    public string text;
        
    [Tooltip("These are the children of this script. They are usually used as choices for Dialogue.")]
    [SerializeField]
    private List<Quest> children;
}

I then have a class called Quests which is a MonoBehavior script which stores Quest objects in a list( public List<Quest> list;) for look-ups, but also has some methods for adding/removing/moving quests.

Quests is meant to be held by a managing script which is just used for UI calls, as well as saving data, but that is outside the scope of this post.

The idea, is that my Manager script would do look-ups on my Quests script, which would contain a list of Quest parts, and the parts could hold a reference to a method and call it when needed.

So, now that you know what I was trying to do, here’s how I tried to solve my issue.

First, I tried looking for some way to reference a generic Script object (i.e public Script script) that would hold a method of a specific name that I could call (i.e script.MethodToCall()). However, as you can guess, no such thing exists.

I then tried using an override, but I then realized I had no way to actually override the function help within the Quest script, as it was a serializable object in a list, added using the inspector (not through a script).

If you have another solution to this problem, feel free to post it. Also feel free to comment about how terrible of code I write :stuck_out_tongue:

The way I solved this issue is by taking advantage of UnityEvents. UnityEvents are really great, and now that I know about them I think I’ll be using them a lot more. (If you don’t know what ‘UnityEvents’ are, they’re what you see on a UI Button, called ‘OnClick’ (where you drag scripts) you can find more info here: Unity - Manual: UnityEvents)

Basically, in my Quest.cs script, above my Quest class, I added a simple mock-class: public class EventTrigger : UnityEvent {} which I would reference in my Quest class like this: public EventTrigger questEvent;. I could then invoke all the methods attached to that script using: questEvent.Invoke()

It looks like this:

using UnityEngine.Events;

[System.Serializable]
public class EventTrigger : UnityEvent {}

[System.Serializable]
public class Quest
{
    public EventTrigger questEvent;

    // Event Triggers
    public void CallEvent() {
        questEvent.Invoke();
    }
}