Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Question Trouble with scriptable objects

Discussion in 'Scripting' started by YKurebayashi, Aug 16, 2020.

  1. YKurebayashi

    YKurebayashi

    Joined:
    Nov 25, 2019
    Posts:
    17
    Hi.
    I`ve been studying a little about scriptable objects, since its my first time actually doing something with it, and I`m 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
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class OverallDisplay : MonoBehaviour
    6. {
    7.     public PlayerCard[] usedCards;
    8.     public GameObject[] usedPlayers;
    9.  
    10.     // Start is called before the first frame update
    11.     void Start()
    12.     {
    13.        
    14.     }
    15.  
    16.     // Update is called once per frame
    17.     void Update()
    18.     {
    19.         usedPlayers = GameObject.FindGameObjectsWithTag("FirstLine");
    20.         for (int i = 0; i < usedPlayers.Length; i++)
    21.         {
    22.             usedCards[i] = usedPlayers[i].GetComponent<PlayerCard>();
    23.         }
    24.     }
    25. }
    26.  
    the code for the scriptable object
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5.  
    6. [CreateAssetMenu(fileName = "New Card", menuName = "Cards")]
    7. public class PlayerCard : ScriptableObject
    8. {
    9.     public string playerName;
    10.     public string description;
    11.  
    12.     public Sprite artwork;
    13.  
    14.     public int farm;
    15.     public int fight;
    16.     public int vision;
    17. }
    18.  
    The script for displaying the card on the Canvas
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5.  
    6. public class CardDisplay : MonoBehaviour
    7. {
    8.  
    9.     public PlayerCard card;
    10.  
    11.     public Text nameText;
    12.     public Text descriptionTex;
    13.  
    14.     public Image artworkCharacter;
    15.  
    16.     public Text farmText;
    17.     public Text fightText;
    18.     public Text visionTex;
    19.     // Start is called before the first frame update
    20.     void Start()
    21.     {
    22.         nameText.text = card.playerName;
    23.         descriptionTex.text = card.description;
    24.  
    25.         artworkCharacter.sprite = card.artwork;
    26.  
    27.         farmText.text = card.farm.ToString();
    28.         fightText.text = card.fight.ToString();
    29.         visionTex.text = card.vision.ToString();
    30.        
    31.     }
    32.  
    33. }
    34.  
     
  2. Terraya

    Terraya

    Joined:
    Mar 8, 2018
    Posts:
    646
    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:

    Code (CSharp):
    1. [CreateAssetMenu(fileName = "New Item", menuName = "Item")]
    2. public class BaseItem: ScriptableObject
    3. {
    4.      [SerializeField ]private string itemName;
    5.      public string ItemName => itemName;
    6. }
    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:

    Code (CSharp):
    1. public class Pickable : Monobehaviour {
    2.  
    3.     public BaseItem baseItem;
    4.  
    5. }
    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:

    Code (CSharp):
    1. public class Pickable : Monobehaviour {
    2.  
    3.     public BaseItem baseItem;
    4.  
    5.  
    6.     private void Start() => print(baseItem.ItemName);
    7.    
    8. }
    im writing the code here on the page, so i hope that there are no errors in it :)
     
    YKurebayashi likes this.
  3. YKurebayashi

    YKurebayashi

    Joined:
    Nov 25, 2019
    Posts:
    17
    Hey, thank you for your answer! :)
    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 I`d 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.
    I`m 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.
     
  4. Terraya

    Terraya

    Joined:
    Mar 8, 2018
    Posts:
    646
    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:

    Code (CSharp):
    1. public class CardDisplay : MonoBehaviour
    2. {
    3.     [SerializeField] private PlayerCard card;
    4.     public PlayerCard Card => card;
    5.  
    6.     public Text nameText;
    7.     public Text descriptionTex;
    8.     public Image artworkCharacter;
    9.     public Text farmText;
    10.     public Text fightText;
    11.     public Text visionTex;
    12.  
    13.     // Start is called before the first frame update
    14.     void Start()
    15.     {
    16.         nameText.text = card.playerName;
    17.         descriptionTex.text = card.description;
    18.         artworkCharacter.sprite = card.artwork;
    19.         farmText.text = card.farm.ToString();
    20.         fightText.text = card.fight.ToString();
    21.         visionTex.text = card.vision.ToString();
    22.  
    23.     }
    24. }
    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:

    Code (CSharp):
    1. public CardDisplay[] cardDisplays;
    2.  
    3. private void GetPlayerCards = () => cardDisplays= FindObjectsOfType<CardDisplay>();
    4.  
    5.  
    then you just need to read whats inside

    Code (CSharp):
    1. private int ReturnSummedFarmValue = () {
    2.    int summedValue = 0;
    3.    foreach(PlayerCard pCard in cardDisplays.Card) {
    4.       summedValue += pCard.farm;
    5.    }
    6.    return summedValue
    7. }
    Small Reminder: I dont use the Editor so small errors are maybe inside