How To Accept Script Reference In Inspector

Hello, I am trying to code a Scriptable Object that can take a script as a parameter.
I want it to preform different custom methods depending on which script I assign.

I thought of using interfaces, but I’m not sure how to make such a parameter appear in the inspector.

I want this:

[CreateAssetMenu(fileName = "New Card", menuName = "Card")]
public class Card : ScriptableObject
{
    public string text;
    public Color textColor = new Color(0.3f, 0.2f, 0.1f, 1);
    public Color cardColor = new Color(1, 0.9f, 0.8f, 1);
    public CardEffect cardEffect;
}


public interface CardEffect {
    public void Effect(CardsManager cardsManager) {}
}

To look like this:

Does anyone know how I might be able to accomplish this?
Also, this is my first time trying to use interfaces to any advice/corrections would be appreciated as well.

Thanks in advance

Script assets are just text files, and they’re editor only. They don’t actually represent an instance of a class/type.

If you want to serialise an instance of a non-Unity object type with polymorphism, that’s where the SerializeReference attribute comes in: Unity - Scripting API: SerializeReference

Caveat is that there isn’t good inspector support out of the box for it, so you’ll need editor addons to make it workable.

2 Likes

Also, as Spiney taught me, you can use TypeCache to get a collection of types of scripts you care about, then make a property drawer or editor that lists them in a dropdown menu. When you select a type of script you can then display the properties you want to display.

(If that is, in fact, the proper description of what you’re trying to do.)

2 Likes

I looked in the documentation and that might work, but how can I instantiate the class of the selected Type?

You can do that with the Activator class from the general C# code library: https://learn.microsoft.com/en-us/dotnet/api/system.activator?view=net-7.0

In some circumstances you may want to use reflection to get the constructor and invoke that: https://learn.microsoft.com/en-us/dotnet/api/system.type.getconstructor?view=net-7.0

If you want to use the inspector for injection, make those actions ScriptableObjects as well, implementing a common interface with an Execute method enforced, so you can always call it and implement per-type behavior. And then you can create different instance of different type of SOs and drag and drop into inspector and/or instantiate from code and refer to them the same way as always.

2 Likes

Thanks for the help!

I did some searching online based off what you suggested and found this helpful article: Use ScriptableObjects as Delegate Objects | Unity

All I had to do was define an abstract class that inherits from Scriptable Object:

public abstract class CardEffect : ScriptableObject {
    public abstract void Effect();
}

And then I can write scripts to define custom methods that override the abstract class:

[CreateAssetMenu(menuName = "CardEffects/AddDie", fileName = "New Effect")]
public class Effect_AddDie : CardEffect
{
    public override void Effect() {
        Debug.Log("One Die Is Added");
    }
}

Then I can define a reference to the abstract class and drag and drop the scriptable objects containing the code I want to execute:
9455945--1327946--Screenshot 2023-11-07 123026.png

1 Like