Search Unity

Help with inventory item slot UI system

Discussion in 'Scripting' started by PaperMouseGames, Jun 17, 2019.

  1. PaperMouseGames

    PaperMouseGames

    Joined:
    Jul 31, 2018
    Posts:
    434
    Hi there! I'm having some trouble with the logic behind my item slots in my inventory UI.

    The behaviour I want is that when I call this method, the method will check the
    List<GameObject> itemSlots
    (which is a list that holds the item slots that are instantiated from the ItemSlot prefab) against the
    playerInventory.InventoryList
    (which holds Items).

    Then I want to add and remove the gameobjects from itemSlots depending on the playerInventory (ie the list should update as I pick up and drop items)

    Here is my current code:

    Code (CSharp):
    1. public void UpdateUI()
    2.     {
    3.         for (int i = 0; i < playerInventory.InventoryList.Count; i++)
    4.         {          
    5.             if (playerInventory.InventoryList[i] != null)
    6.             {
    7.                 Debug.Log("Creating new inventory slot...");
    8.                 itemSlots.Add(Instantiate(itemSlot, contentPanel.transform));
    9.                 itemSlots[i].transform.SetParent(contentPanel.transform);
    10.                 ItemSlot newSlot = itemSlots[i].GetComponent<ItemSlot>();
    11.                 newSlot.AddItem(playerInventory.InventoryList[i]);
    12.             }
    13.         }
    14. }
    Currently the items are being added, but the problem is, that every time I call UpdateUI it adds new empty buttons from my prefab. I know why this is happening, because every time I call UpdateUI it checks to see if i = 0 is less than playerInventory.InventoryList.Count, which is always true, but I don't know how to fix it.

    I also don't know how to remove those UI elements once they've been Instantiated (ie if the player drops an item).

    I think I could do this by defining an array of a specific size and adding the items in, then setting the item slots's visibility with SetActive, but then I've have to define an inventory size, and I didn't wanna do that.

    Any tips would be most welcome, thanks!
     
  2. WallaceT_MFM

    WallaceT_MFM

    Joined:
    Sep 25, 2017
    Posts:
    394
    Here's a little pseudo code for how I would think of this:
    Code (csharp):
    1.  
    2. public void UpdateUI()
    3. {
    4.    // addList = empty
    5.    // removeList = empty
    6.    // slotList = every item already in a slot
    7.    // For each item in the player's inventory
    8.    //     if slotList does not contain item
    9.    //          add item to addList
    10.    // For each item in slotList
    11.    //     if item is not in player's inventory
    12.    //          add item to removeList
    13.    // Remove all items in removeList from slotList and the actual slot objects
    14.    // Add all items in addList to the actual slots
    15. }
    So, from a high level, I'd do it in a couple of passes. There shouldn't be any serious performance problem with this unless you have 10's of thousands of items. At that point, you may need a different design.
     
  3. PaperMouseGames

    PaperMouseGames

    Joined:
    Jul 31, 2018
    Posts:
    434
    This makes sense to me as I've done similar logic before when dealing with replacing items on lists, but the thing that I can't seem to figure out is the las bit of your code:

    Code (CSharp):
    1.    // Remove all items in removeList from slotList and the actual slot objects
    2.    // Add all items in addList to the actual slots
    The "Remove... the actual slot objects" is what's tripping me up. I can't seem to figure out a way of removing the empty slot objects, when I'm instantiating these slot objects onto the UI.

    I'm currently trying to add them to a list as I instantiate them but that doesn't really seem to be working either.

    EDIT: To clarify, the part I'm having the most trouble with is the adding/creating and removing/destroying of the actual slot GameObjects onto the GUI. In the past I've added them all to a grid and simply enabled or disabled them as needed, but I wanted to have more flexibility to add more items to the inventory without having to add thousands of premade slots and disable them all. Maybe I'm going about it wrong though and having them premade is the better way of doing things though, I don't know honestly.
     
    Last edited: Jun 18, 2019
  4. WallaceT_MFM

    WallaceT_MFM

    Joined:
    Sep 25, 2017
    Posts:
    394
    I don't have the rest of your code but I think something like this would work:
    Code (csharp):
    1. for(int i = 0; i < contentPanel.childCount; i++)
    2. {
    3.     ItemSlot slot = contentPanel.GetChild(i).GetComponent<ItemSlot>();
    4.     if(slot == null) continue; // Skip to next loop early if this child didn't have a slot
    5.     if(removeList.Contains(slot.item) || slot.item == null) // I assume your ItemSlot script has some way of knowing what item is in it, or if it doesn't have an item
    6.     {
    7.         Destroy(slot.gameObject);
    8.         i--; // Destroying things in a list as you iterate can be very dangerous, be careful
    9.     }    
    10. }