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) {}
}
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.
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.
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.)
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.
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: