Don't know how to set up my class structures....

Hi there,

So I am getting this “You are trying to create a MonoBehaviour using the ‘new’ keyword. This is not allowed.” error.
But I sense, that I should probably not be doing what I was trying to do anyway. :slight_smile:
I am new to Unity and I only used to do a little bit with Java some years ago.

The end goal is a card game, in which the cards are dynamically assembled in a list before any gameObjects are instantiated and distributed in the scene.

So I created a new script defining a card class derived from monobehavior with some attributes, functions and a constructor.
I then attached that script to a 3d model card prefab.
And finally I tried to fill up the list of cards in another ‘higher level’ script.
That is when I came across the error mentioned above.

Here it is in shortened/simplified code:

public class CardObject : MonoBehaviour    {
    public int card_id;
    public int icon_number;
    public int color;
    public int background_type;
    public bool reveal;

    Animator my_animator;
    GameManager my_game_manager;

    // constructor
    public CardObject(int new_card_id, int new_icon_number, int new_color, int new_background_type, bool new_reveal)    {
        card_id = new_card_id;
        icon_number = new_icon_number;
        color = new_color;
        background_type = new_background_type;
        reveal = new_reveal;
    }
   
    // ----------------------------------------------------------------------------

    private void Awake()   {
        my_animator = GetComponent<Animator>();
        reveal = false;
        my_animator.SetBool("reveal", reveal);
        my_game_manager = GetComponentInParent<GameManager>();
    }

    // ----------------------------------------------------------------------------

    private void OnMouseDown()    {
        //...
    }

    public void FlipTo(bool showFace)    {
        //...
    }
    //and so on...
}
public class GameCreator : MonoBehaviour {
    // ...
    List<CardObject> cards;
    // ...

    // ----------------------------------------------------------------------------

    void Start () {
        //...
        cards = new List<CardObject>();
        //...
        cards.Add(new CardObject(cards.Count, 1, 2, 0, false));
        //...
}

Now, I don’t know if I even have the right approach to my whole structure.
I realize, I should not be creating instances that are not yet linked to any gameObjects. And I also just read, that should not use a constructor in a monobehavior class anyway.

So what is the best practice here.
Should I maybe separate the card class from the script attached to the 3d object, so that it do not need monobehavior?

Or, should turn around the order of things and initialize all cards as ‘general purpose’ objects in the scene and only later manipulate them by adding or deactivating components, changing attributes and so on?

And how does adding a new card item into the list actually look in the end (without a constructor and whatnot)?

Thanks in advance.

Id recommend splitting your Card class and your CardObject. Ideally you would have your CardObject which derives from MonoBehaviour and that CardObject has a reference to the Card it represents. The way I think of it is, what is the data is needs to hold, (Data class that doesn’t derive from monobehaviour) and what does the object do when in the game world? (CardObject that derives from monobehaviour). This way, you will be able to change what your cards do in the game world without affecting your card data structure.

For example

public class Card {
    public Card ( //params... ) {
        //Constructor
    }
}
public CardObject : MonoBehaviour {
    public Card card; //This object represents this card.
    // Start (), Awake(), Update().... etc....
}

How you then define which card the cardobject represents is then up to you.
I’ve been working on a card game for a while and will be happy to share some of my implementation with you.

Thanks a lot.

It feels a bit strange to separate data and behavior in different places for now, but what do I know… :slight_smile:

You don’t have to, and that was just an idea. In lieu of a constructor, which you read correctly shouldn’t be used, you can always create your own method to initialize (“like a constructor” in that sense).

public void Init(/*parameters I didn't copy/paste */)

:slight_smile:

1 Like

As @methos5k said, you don’t HAVE to but for me, I found it much easier to manage.

Ya, well @Malleck666 's idea is also good. So now you have 2 options… If you stick around for a while, you’ll probably use both someday with one thing or another :wink:

1 Like