Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Using Scriptable Objects with Dictionaries

Discussion in 'Scripting' started by BoBB1BoBB1, Jul 22, 2022.

  1. BoBB1BoBB1

    BoBB1BoBB1

    Joined:
    Oct 21, 2017
    Posts:
    3
    Hey there!

    I've been using a lot of key/value pairings at work lately where the value is some kind of object. So I decided to try it out in C# within Unity! However, I can't quite get it to work.

    I had this "brilliant" idea for an inventory system where I would make a scriptable object for each inventory item type. This would store the name, description, sprite, whatever. Then I could reference the dictionary key to find the value I want and I would then only need one simple script controlling the inventory backend.

    However... it seems I have an error:
    error CS1061: 'int' does not contain a definition for 'quantity' and no accessible extension method.... etc.

    The error message makes sense to me. What I am trying to determine is how to access a public variable in a scriptable object from a script within a dictionary. But it seems to think it is an int (which makes sense as it is in square brackets) but I'm not sure how else to write this.

    Any help is much appreciated!! Thanks in advance :)
    If more information is required let me know!

    This is the file for the scriptable object:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5.  
    6. [CreateAssetMenu(fileName = "ItemData", menuName = "Items/ItemData", order = 0)]
    7. public class ItemData : ScriptableObject {
    8.     public string displayName;
    9.     public int quantity;
    10.     public Sprite icon;
    11.     public string flavourText;
    12. }
    13.  
    And this is the script for the inventory:
    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class PlayerInventory : PlayerCurrency {
    7.     public Dictionary<string, ItemData> inventoryItems = new Dictionary<string, ItemData>();
    8.  
    9.     void Awake(){
    10.         //TODO: Set items = saved item value
    11.         currencies.Add("testItem", 0);
    12.         currencies.Add("testItem2", 0);
    13.     }
    14.     public int GetItemNumber(string itemType)
    15.     {
    16.         int value = 0;
    17.         try{
    18.             value = (inventoryItems[itemType].quantity);
    19.         }
    20.         catch (Exception e){
    21.             Debug.Log("Item Type does not exist (get)");
    22.         }
    23.         return value;
    24.     }
    25.  
    26.     public void SetCurrency(string itemType, int amount)
    27.     {
    28.         try{
    29.             currencies[itemType].quantity = amount;
    30.         }
    31.         catch(Exception e){
    32.             Debug.Log("Item Type does not exist (set)");
    33.         }
    34.     }
    35.  
     
  2. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    6,008
    Why are you using try-catch methods?

    Dictionary's have a boolean method called TryGetValue. You should be using that.

    Also note that Unity can't serialise dictionaries.
     
  3. BoBB1BoBB1

    BoBB1BoBB1

    Joined:
    Oct 21, 2017
    Posts:
    3
    Thanks for the response!

    Did not know that method existed for dictionaries! Good to know.

    Hmmmm. The lack of serialization might be problematic. But I don't need it to be in the editor, I just need to be able to pull the data. Not sure if that's possible...
     
  4. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    6,008
    If you only plan to populate it at run time, that's fine. You just won't be able to design it at edit time, which for me would be a deal breaker. There are plenty of methods to make it possible though; something for you to google. Or you can just use regular lists, as it's doubtful there will be any significant performance impact unless you have boatloads of items.

    I also don't know about storing the quantity of an item in the SO itself. This value be used by any references to the SO, so you can't, say, have x quantity in one place and y quantity in another place. You may be better off making a wrapper class that represents a quantity of an item.
     
  5. BoBB1BoBB1

    BoBB1BoBB1

    Joined:
    Oct 21, 2017
    Posts:
    3
    Thanks again for the response! Yea I think I found a way to make it work, but it's probably more hassle than it's worth.

    Probably best to just use a list! Always nice to learn something new though!
     
    spiney199 likes this.
  6. Rotary-Heart

    Rotary-Heart

    Joined:
    Dec 18, 2012
    Posts:
    804
    There are solution for that problem in the asset store, so you can go take a look. I have a free one available too