Trouble with scriptable objects

Hi.
Ive been studying a little about scriptable objects, since its my first time actually doing something with it, and Im just a beginner, i`m finding a hard time to access the data each object is holding.

I created an array that is called usedPlayers, these are the objects that holds these datas.
And i`d like to access individually each one of the variables inside these objects.
What I tried to do is create another array, that would be an array to get these data from the objects.
But when I play the project it says: getcomponent requires that the requested component “playercard” derives from MonoBehaviour or Component or is an Interface.

I don’t know if its possible to do what i’m trying to do (to get these scriptable objects data by creating an array of them, so I can use them withouth problem later in this same script).

If someone could give me a hint on how to do this, I`d be really thankfull.

The code i`m struggling with

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class OverallDisplay : MonoBehaviour
{
    public PlayerCard[] usedCards;
    public GameObject[] usedPlayers;

    // Start is called before the first frame update
    void Start()
    {
       
    }

    // Update is called once per frame
    void Update()
    {
        usedPlayers = GameObject.FindGameObjectsWithTag("FirstLine");
        for (int i = 0; i < usedPlayers.Length; i++)
        {
            usedCards[i] = usedPlayers[i].GetComponent<PlayerCard>();
        }
    }
}

the code for the scriptable object

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


[CreateAssetMenu(fileName = "New Card", menuName = "Cards")]
public class PlayerCard : ScriptableObject
{
    public string playerName;
    public string description;

    public Sprite artwork;

    public int farm;
    public int fight;
    public int vision;
}

The script for displaying the card on the Canvas

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class CardDisplay : MonoBehaviour
{

    public PlayerCard card;

    public Text nameText;
    public Text descriptionTex;

    public Image artworkCharacter;

    public Text farmText;
    public Text fightText;
    public Text visionTex;
    // Start is called before the first frame update
    void Start()
    {
        nameText.text = card.playerName;
        descriptionTex.text = card.description;

        artworkCharacter.sprite = card.artwork;

        farmText.text = card.farm.ToString();
        fightText.text = card.fight.ToString();
        visionTex.text = card.vision.ToString();
       
    }

}

Hey there!

So first of all, a small recommendation for ScriptableObjects,
use them “only” if their Values doesnt get changed runtime,

thats sayd,

let me explain you how to access the Data from a ScriptableObject,

lets create an Item:

[CreateAssetMenu(fileName = "New Item", menuName = "Item")]
public class BaseItem: ScriptableObject
{
     [SerializeField ]private string itemName;
     public string ItemName => itemName;
}

that Item have a field “itemName”, so first of, we have to Create that ScriptableObject ,
we go under Assets → Rightclick → on top “Item”

now that Item is Created, we need another Script to hold that information for us,
lets say its kind of an Item we want to pickup, so we do an Monobehaviour:

public class Pickable : Monobehaviour {

    public BaseItem baseItem;

}

so now, we create a sphere in the Scene, we add the script “Pickable” to the Sphere, drag the new ScriptableObject we created before to the baseItem field in the inspector(you need to have the sphere selected)

and now to access its data you can for example do this:

public class Pickable : Monobehaviour {

    public BaseItem baseItem;


    private void Start() => print(baseItem.ItemName);
    
}

im writing the code here on the page, so i hope that there are no errors in it :slight_smile:

1 Like

Hey, thank you for your answer! :slight_smile:
But I think I may have expressed myself not so clearly.
I’d like to access these infos not in the object, but in a 3rd object that is not a scriptableobject.
I have like a game manager that would have an array of the scriptableobjects that are tagged “FirstLine”, and Id like to get a int value from each scriptableobject and sum all of them together. Thats why I created two arrays, one for the selected objects that are tagged firstline and another one for these int values, but it ended up not working. Im so sorry to express myself badly, english is not my first language.
Anyway, thank you for your help, it ended up being good for me to understand better these things.

So well, to represent ScriptableObjects as “3D” Objects,
you need a “Container” Object for your ScriptableObject,

so, as i can see, this is your Container Object:

public class CardDisplay : MonoBehaviour
{
    [SerializeField] private PlayerCard card;
    public PlayerCard Card => card;

    public Text nameText;
    public Text descriptionTex;
    public Image artworkCharacter;
    public Text farmText;
    public Text fightText;
    public Text visionTex;

    // Start is called before the first frame update
    void Start()
    {
        nameText.text = card.playerName;
        descriptionTex.text = card.description;
        artworkCharacter.sprite = card.artwork;
        farmText.text = card.farm.ToString();
        fightText.text = card.fight.ToString();
        visionTex.text = card.vision.ToString();
 
    }
}

lets say you want to sum all of yours “farm” variables from all your “PlayerCards” attached to all your “CardDisplays”,

first you will need to get all of them:

public CardDisplay[] cardDisplays;

private void GetPlayerCards = () => cardDisplays= FindObjectsOfType<CardDisplay>();

then you just need to read whats inside

private int ReturnSummedFarmValue = () {
   int summedValue = 0;
   foreach(PlayerCard pCard in cardDisplays.Card) {
      summedValue += pCard.farm;
   }
   return summedValue
}

Small Reminder: I dont use the Editor so small errors are maybe inside