How do I serialize method calls?

The title might be a little misleading. I’m not exactly sure that serializing method calls is what I actually want to do. What I need is to be able to have a field in a ScriptableObject that lets me set a method to be called. For example, in a card game, I want to be able to set a field that decides whether a spell is a heal spell or a damage spell with other fields indicating the target and amount. In another game, I needed to add effects to projectiles. I ended up using enums and a static class that had a method that took the enum and decided which method to call. It felt a bit unwieldy. There has to be a better way. Is there some kind of standard practice for this?

Do you know about UnityEvents?

1 Like

Another option would be to use an abstract base class that defines a method shared by all the implementing classes.

public abstract class Spell : ScriptableObject
{
    public abstract void Cast();
}

[CreateAssetMenu]
public class HealSpell : Spell
{
    public override void Cast()
    {
        // implement heal spell here
    }
}

Then drag-and-drop the spell you want to use:

[SerializeField]
private Spell spell;

public void CastSpell()
{
    spell.Cast();
}

UnityEvents are super flexible, but also have some downsides. Deserialization can fail silently if a method referenced by an UnityEvent field is renamed for example. And a method can appear like it’s not being used at all in the IDE, and somebody could go ahead and delete it, not knowing that it’s actually being referenced by an UnityEvent on some asset.

I’m just going to link my post in another thread from yesterday with basically the same question: Is there a way to store functions in scripts that have no context for them?

Personal preference is SerializeReference, though this does require custom inspector support.

1 Like