item quantity, code structure issue

i originally made this an Item property (a variable in the scriptable object Item), but code that changes the value of the inventory actually changes the value of the item’s quantity in the inspector. i have multiple inventories in the game, so this doesn’t work. how could i restructure my code to make quantity separate but still accessible?

some object is untiy have their properties serialized even at runtime take materials for example , if you dont create another instance at runtime any changes you make at runtime will persist afterwards. a scriptable object is also an object that has its properties serialiized at runtime . If you dont want that then use and a monobehavior attached to a gameobject.

1 Like

Makes sense to have a “holder object” for items.
A simple example might be…

public class Holder : MonoBehaviour
{
  Item item;
  int count;
}
2 Likes

You can also use [NonSerializable] attribute to make sure value isn’t changed. Though you would have to use OnEnable(…) to copy values from inspector to temporary variable.

Note that everything in ScriptableObject is considered “one” object’s properties if you don’t copy them at runtime.
I’d suggest using MonoBehaviour and copy everything that is dynamic there.

1 Like

i’m drawing a blank. how could i link an item holder class to my inventory at a given index? for example, in the following code for my inventory:

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

namespace CoS
{
    public class heroInventory : MonoBehaviour
    {
        public Canvas hinventorycanvas;
        public int invcapacity = 50;
        public Item[] inventory;

        public Canvas hinvequippedcanvas;

        public GameObject hero;

        public GameObject grounditemprefab;

        private bool inventoryflag = false;

        // Use this for initialization
        void Awake()
        {
            bool inventoryflag = false;

            hinventorycanvas.enabled = false;
            hinvequippedcanvas.enabled = false;
            Item[] inventory = new Item[invcapacity];

            //grounditemprefab = new GameObject();
            // going to have to refactor this later.  can't re-initialize inventory at the beginning of every scene!
            //doesn't work anyway
            for (int i = 0; i < invcapacity; i++)
            {
                inventory[i] = ScriptableObject.CreateInstance("Item") as Item;
                inventory[i].objname = "Nothing";
                inventory[i].description = "nothing";
                inventory[i].price = 0;
                inventory[i].sprite = "InvIconNothing";
                inventory[i].type = "";
                inventory[i].dr_crushing = 0;
                inventory[i].dr_cutting = 0;
                inventory[i].dr_impaling = 0;
                inventory[i].pd_crushing = 0;
                inventory[i].pd_cutting = 0;
                inventory[i].pd_impaling = 0;
                inventory[i].thrusting = "";
                inventory[i].swinging = "";
                inventory[i].thrusting_modifier = 0;
                inventory[i].swinging_modifier = 0;
            }
        }

        // Update is called once per frame
        void Update()
        {
            if (Input.GetKeyDown(KeyCode.I))
            {
               hinvequippedcanvas.enabled = !hinvequippedcanvas.enabled;
            }

            if (inventoryflag)
            {
                ShowInventory();
            }


        }
     
        public void XButton()
        {
            hinventorycanvas.enabled = false;
            inventoryflag = false;
        }

        public void InventoryIconButton()
        {
            hinventorycanvas.enabled = true;
            inventoryflag = true;
           // ShowInventory();
        }

        /**********************
         * Inventory Functions
         * *******************/
        // remove from inventory
        public void Inv_Remove(Item item, int qnty)
        {
            //In the script we will remove an item from the inventory
            var found = -1;
            if (item.objname == "Nothing")
                return;

            //We will check if the item exists and take its place
            for (var i = 0; i < 5; i++)
            {
                //ItemID eyedee1 = (ItemID)i;
                if (inventory[i].objname == item.objname) //maybe have a unique id rather than use name?  possibility.
                {
                    found = i;
                    break;
                }
            }

            if (found != -1)
            {
                //If we found the item, we remove it
                inventory[found].quantity -= qnty;//qnty is the amount to remove
                if (inventory[found].quantity <= 0)
                {
                    inventory[found] = ScriptableObject.CreateInstance("Item") as Item;
                    inventory[found].objname = "Nothing";
                    inventory[found].description = "nothing";
                    inventory[found].price = 0;
                    inventory[found].sprite = "InvIconNothing";
                    inventory[found].type = "";
                    inventory[found].dr_crushing = 0;
                    inventory[found].dr_cutting = 0;
                    inventory[found].dr_impaling = 0;
                    inventory[found].pd_crushing = 0;
                    inventory[found].pd_cutting = 0;
                    inventory[found].pd_impaling = 0;
                    inventory[found].thrusting = "";
                    inventory[found].swinging = "";
                    inventory[found].thrusting_modifier = 0;
                    inventory[found].swinging_modifier = 0;
                }  //If there is no more of the item we change the place to an empty place (Nothing item)
            }
        }

        //In this script we will add items to the inventory
        public void Inv_Add(Item item, int qnty)
        {
            var found = -1;
            bool fullflag = false;

            if (item.objname == "Nothing")
                return;

            for (var i = 0; i < invcapacity; i++)
            {
                if (inventory[i].objname == item.objname)
                {
                    found = i; //We affect to found the place of the item if we find it
                    break;
                }
            }

            //If it doesn't exist

            if (found == -1)
            {
                //Let's check if there is an empty place to add our item
                for (var j = 0; j < invcapacity; j++)
                {
                    if (inventory[j].objname == "Nothing")
                    {
                        found = j;
                        break;
                    }
                    else if (j == (invcapacity - 1) && found != j)
                    {
                        fullflag = true;
                        break;
                    }
                }
            }

            //should have an "inventory is full" contingency
            if (fullflag)
            {
                // print this out!  in a game-friendly gui - depends on whether looting or picking up, or buying
                Debug.Log("inventory is full, cannot pick up object");
            }

            //Now let's add our item to the place we have *
            if (found != -1)
            {
                inventory[found] = item; //Argument 0 is the id of the item
                inventory[found].quantity += qnty; //Argument 1 is the amount of the item to add
            }
            // need a script for looting, for buying, and for picking up
        }

        // Drop an item
        public void Inv_Drop(Item item1)
        {
            // item = item clicked in gui - right click and click drop
            //Instantiate(hero, item);
            //not sure what to use in place of "item"
            //use groundobject prefab
            if (item1.objname == "Nothing")
            {
                // show can't drop nothing message or make noise
                return;
            }
            Inv_Remove(item1, 1);
            GameObject gogi = new GameObject();
            gogi = Instantiate(grounditemprefab, new Vector3(0, 0, 0), Quaternion.identity);
            gogi.transform.position = hero.transform.position += new Vector3(1, 1, 0);
            GroundItem grounditem = gogi.GetComponent <GroundItem>();
            grounditem.item = item1;

        }

        //Pick up item
        public void Pick_Up(Item item)
        {
            Inv_Add(item, 1);
        }

    // got to look at GM to figure out the types for the inventory
    void ShowInventory()
        {
            string labeltxt = "";
            string labelimg = "";
            int counter = 0;
            for (int i = 0; i < invcapacity; i++)
            {
                counter = i + 1;
                //update icon and text
                labeltxt = "Text" + counter;
                labelimg = "Image" + counter;

                Text text = GameObject.Find(labeltxt).GetComponent("Text") as Text;
                text.text = inventory[i].objname + " x " + inventory[i].quantity;
                Image image = GameObject.Find(labelimg).GetComponent("Image") as Image;
                Sprite invicon = Resources.Load<Sprite>(inventory[i].sprite);
                image.sprite = invicon;
            }
        }
    }
}

see lines 110, 111, and 182.

If you were expanding upon my post, I’d say that using Holder [ ] inventory instead of Item [ ] inventory would be how I would do it :slight_smile:

1 Like