How to manage ScriptableObjects ?

Hello Unity community!
2 questions:

I try to use correctly scriptables objects, but I not really sure about how to manage them.

  • Do I have to store them (after a initiate) in a GameObject Array, List, other?

And for exemple, I made a cards game, when i use a cards (drop it on an enemy).

  • What the best way to retrieve variables and fonctions of this specific card in the array with all my scriptables cards?

Thanks!

An instance of a ScriptableObject definition is data that you can reference everywhere. In your case, such an instance could represent a card in your game. How you organize these instances, that is up to you and your need in the game.

What you could do, for example, is creating a SO instance for every card in your game and if the player has a collection of cards, appropriately reference them there. Note that SO instances alone usually do not solve everything, often you need wrappers. If a player has collected a card, for instance, such a simple wrapper could look like this:

public class CardCollection : MonoBehaviour {

    [Serializable]
    public class CollectedCard {
        public Card instance; // Card : ScriptableObject
        public int amount;
    }

    [SerializeField]
    private CollectedCard[] collected;
}

In other words, ScriptableObjects are a good start, but you will usually need to build around them, not just with a simple list or array, but complex structures, containers and wrappers.

1 Like

Really interesting, it also could use for a deck. I will try to use this for now and come back later if I have question.

thanks for yours tips!

Hello again,

I not really sure about how to find and add my SO in my class.
Now I have 1 prefab (a card) and several SO that change attribute of my card.

Edit: I make a struct that store all my cards generated:

  • When I use Class rather than Struct it doesn´t work, i don´t know why? → “NullReferenceException: Object reference not set to an instance of an object” on these lines:

  • playerDeck*.Cards = initCard;*
    - playerDeck*.amount = 1;*

  • [/i]*
    any idea?
    - Is it a good start? What can I improve?
    ```csharp
    *public class Deck : MonoBehaviour
    {
    [Serializable]
    public struct PlayerDeck
    {
    public GameObject Cards; // Card : ScriptableObject
    public int amount;
    }

    public PlayerDeck playerDeck;

    /***** Prefab card *****/
    public GameObject prefabCard;
    public SoCards tmpSoCards;
    public string results;
    public GameObject initCard;

    /***** Parent *****/
    public GameObject cardsList;

    public void Start()
    {
    prefabCard = GameObject.FindGameObjectWithTag(“Prefab Card”);
    cardsList = GameObject.FindGameObjectWithTag(“Cards List”); // Game object that will contain all Cards (Game object)

      /***** Init Deck *****/
      results = AssetDatabase.FindAssets("t:SoCards"); // Path of cards SO
      tmpSoCards = new SoCards[results.Length]; //store the path
      playerDeck = new PlayerDeck[results.Length]; //Struct with all cards
    
      for (int i = 0; i < results.Length; i++)
      {
          tmpSoCards[i] = (SoCards)AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(results[i]), typeof(SoCards));
    
          initCard = Instantiate(prefabCard);
          initCard.transform.SetParent(cardsList.transform);
          initCard.name = AssetDatabase.GUIDToAssetPath(results[i]);
          initCard.GetComponentInChildren<CardsEffects>().data = tmpSoCards[i];
          initCard.SetActive(false);
         
          playerDeck[i].Cards = initCard;
          playerDeck[i].amount = 1;
      }
    

    }
    }
    _
    ```*_

A class reference can either reference an instanced object or nothing, whereas a struct always references an instanced object. In other words, if you have a class reference, you have to assign an instanced object to it before using it while when using a struct, you get the default object of that struct type.

To use it as a class, add this to your code:

        playerDeck = new PlayerDeck[results.Length]
        for(int someIndex = 0; someIndex < playerDeck; someIndex++){
            playerDeck[someIndex] = new PlayerDeck();
        }
1 Like