ScriptableObject problem and creating a new class instance

Hi! I ran into a problem with Scriptable Objects. I have a abstract class derived from ScriptableObject. All other cards are inherited from this class, which I assign values ​​in the inspector

    public abstract class CardObject : ScriptableObject
    {
        public Card data = new Card();

        public string Name { get => CardStrings.name; }
        public string RawDescription { get => CardStrings.description; }


        private CardStrings CardStrings { get => Game.Instance.languagePack.GetCardStrings(data.id); }

        public abstract void Play();
    }

What’s the matter. There will be cards in my game, but each one will act absolutely unique, which is why I came to the conclusion that it is better for each card to make its own class, which will just inherit from CardObject

    [Serializable]
    public class Card
    {
        public delegate void CardChange();
        public event CardChange OnCardChange;

        [Header("Base properties")]
        public string id;
        [SerializeField] private int baseDamage = 0;
        [SerializeField] private int baseMagicNumber = 0;

        public int Damage { get => baseDamage; }
        public int MagicNumber { get => baseMagicNumber; }

        public CardObject CardObject { get => Game.Instance.cardManager.cardDatabase.GetCardById(id); }
        public Card()
        {
            id = "";
            baseDamage = 0;
            baseMagicNumber = 0;
        }

        public Card(string cardId) : this(Game.Instance.cardManager.cardDatabase.GetCardById(cardId)) {}

        public Card (CardObject card)
        {
            id = card.data.id;
            baseDamage = card.data.baseDamage;
            baseMagicNumber = card.data.baseMagicNumber;
        }

But after that I thought that it would be better to create a Card class and already inherit each new card from it, overriding only the Play() method, which will be transferred from CardObject to Card class, but I ran into a problem that I use ScriptableObject to set base values for each map, but I don’t know how I can assign a specific Card derived class to a given ScriptableObject. Tell me how I can do this, or even better, if you have any ideas, tell me how you can better implement a system with completely different cards, without creating each class separately for each card.


At the moment, my Card class acts only as a class that is cloned from CardObject to create an initial card.
Also, English is my second language, so if something is not clear, then ask.

You just overcomplicated everything. Unity’s serialization system isn’t really prepared for serializing polymorphic classes besides ScriptableObjects and MonoBehaviours. Since the introduction of the SerializeReference attribute it’s now possible to serialize polymorphic custom serializable classes, however you would need to handle the creation of those classes completely yourself with a custom editor.

I would highly recommend that you just stick to your ScriptableObject class and keep your data in that class. ScriptableObjects can be cloned by default by using Instantiate. In the editor you can directly use “CTRL + d” to duplicate any ScriptableObject asset. You can also create instances of ScriptableObjects at runtime by using the static CreateInstance method. ScriptableObjects, just like MonoBehaviours, do not really support constructors. However if you want to create them at runtime you can either use Instantiate to clone an existing object (asset or object in scene) or / and use an “Init” method which you call after the cloning / creating the object.

Just don’t forget to add the CreateAssetMenu attribute to each of your concrete CardObject classes so you can directly create instances in the editor.