Search Unity

  1. Want to see 2020.1b in action? Sign up for our Beta 2020.1 Overview Webinar on April 20th for a live presentation from our evangelists and a Q&A session with guests from R&D.
    Dismiss Notice
  2. Interested in giving us feedback? Join our online research interviews on a broad range of topics and share your insights with us.
    Dismiss Notice
  3. We're hosting a webinar for the new Input System where you'll be able to get in touch with the devs. Sign up now and share your questions with us in preparation for the session on April 15.
    Dismiss Notice

Help Wanted Removing inventory items

Discussion in 'Game Foundation' started by DemonFangZ, Oct 15, 2019.

  1. DemonFangZ

    DemonFangZ

    Joined:
    Feb 6, 2019
    Posts:
    7
    Hi,

    I recently saw the Game Foundation presentation on YouTube and was very excited to try it out. I was following the tutorial from the documentation, but got stuck at the "Working with Stats at Runtime" step.

    Firstly, in the SharpenSword() function, I think, "scrollDamageIncrease" should be "damageBuffSpell" since we created the Game Item: "Damage Buff Spell" in the previous step.

    Also when I tried:
    Inventory.main.RemoveItem(scrollItem);
    I got an error: cannot convert from 'UnityEngine.GameFoundation.InventoryItem' to 'string'

    So I tried the following and it worked:
    Inventory.main.RemoveItem("damageBuffSpell", 1);
    Well it did work for any quantity greater than 1. I wasn't able to delete the inventory item when the default quantity was set to 1. Am I doing something wrong?
     
    erika_d likes this.
  2. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    6,878
    Can you provide your full script? Please paste here with Code tags, we will take a look
     
  3. DemonFangZ

    DemonFangZ

    Joined:
    Feb 6, 2019
    Posts:
    7
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.GameFoundation;
    5.  
    6. public class WalletTest : MonoBehaviour
    7. {
    8.     void Awake()
    9.     {
    10.         // you always need to call Initialize once per session
    11.         GameFoundation.Initialize();
    12.     }
    13.  
    14.     void Start()
    15.     {
    16.         SharpenSword();
    17.     }
    18.  
    19.     void SharpenSword()
    20.     {
    21.         InventoryItem swordItem = Inventory.main.GetItem("sword");
    22.         InventoryItem scrollItem = Inventory.main.GetItem("damageBuffSpell");
    23.         int swordDamage = StatManager.GetIntValue(swordItem, "damage");
    24.         int damageIncrease = StatManager.GetIntValue(scrollItem, "damageIncrease");
    25.         StatManager.SetIntValue(swordItem, "damage", swordDamage + damageIncrease);
    26.  
    27.         Debug.Log("Scroll quantity: " + scrollItem.quantity);
    28.         Inventory.main.RemoveItem("damageBuffSpell", 1);
    29.         Debug.Log("Scroll quantity: " + scrollItem.quantity);
    30.  
    31.     }
    32. }
     
    erika_d likes this.
  4. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    6,878
    So the above code does not remove the item? So it works only when you put 2 in, instead of 1, for example? What is the Debug.Log output that you have? Also, the documentation is a bit out of date, your string parameter syntax should work.
     
  5. DemonFangZ

    DemonFangZ

    Joined:
    Feb 6, 2019
    Posts:
    7
    Yes, it only works with numbers greater than 1. I'm unable to delete the last item from the inventory.
    For example if I set the default quantity to 5, and then use a button with the following function:
    Code (CSharp):
    1. public void DeleteItem()
    2.     {
    3.         InventoryItem scrollItem = Inventory.main.GetItem("damageBuffSpell");
    4.         Inventory.main.RemoveItem("damageBuffSpell", 1);
    5.         Debug.Log("Scroll quantity: " + scrollItem.quantity);
    6.     }
    After clicking the button 5 times it should be 0, but it stops at 1. If I try to click on the button again I get the NullReferenceException error, as shown in the attached image.

    deleteItem.PNG
     
  6. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    6,878
    So this is different code than you first posted. Your first Scroll quantity log output shows 5, and if you are using the second code snippet that outputs after the RemoveItem, it would imply that you originally have 6 objects, not 5, correct? Also the NRE is after your debug output, I would have expected it right at the RemoveItem call. I suspect however that your testing is correct and it is just your forum post syntax and/or you are mixing the debug output. If there is a bug, it looks to be when removing the last item if so. We will check here also.
     
  7. DemonFangZ

    DemonFangZ

    Joined:
    Feb 6, 2019
    Posts:
    7
    Oh sorry, my mistake. As you said, I did start with 6 objects not 5. I also think there may be a bug when removing the last item, but I'll go through my code again.

    Thanks!
     
  8. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    6,878
    I might suggest that you wait on further testing :) as it appears that we may be holding onto a reference incorrectly on the last item that is removed, and the list still reports (incorrectly) one item remaining. Thanks for the report, we are working on it.
     
    mingz-unity and DemonFangZ like this.
  9. erika_d

    erika_d

    Unity Technologies

    Joined:
    Jan 20, 2016
    Posts:
    321
    Hi @DemonFangZ ,

    As Jeff mentions, there is an issue with item.quantity when RemoveItem(item, amountToRemove) is called with an amountToRemove equal to or greater than the quantity of the item in the inventory (i.e. quantity of 1 and RemoveItem("damageBuffSpell", 1) or quantity of 2 and RemoveItem("damageBuffSpell", 2) etc). The RemoveItem method follows two different code paths, depending on whether it will be removing the last item of that type in the inventory. In the case where the amountToRemove is less than the quantity in the inventory, only the item.quantity is changed by RemoveItem (and your local reference is still pointing to that item and so it picks up the quantity change). In the case where amountToRemove >= item.quantity, the item.quantity value doesn't get changed because the code removes that item from the inventory instead. However, although the item is no longer in the inventory, your local reference to it is still pointing to that item in memory, along with the un-updated quantity value.

    One possible change we can make is to update the quantity to 0, however another thing that we want to address is making it clear that that item you're pointing to no longer exists in the inventory. Probably the ideal situation is we change both things.

    In case it doesn't make sense in words, I'm going to try to represent the inventory status as you go through a couple loops of removes:

    Inventory: main
    - sword: 1
    - damageBuffSpell: 2

    RemoveItem("damageBuffSpell", 1)

    Inventory: main
    - sword: 1
    - damageBuffSpell: 1

    RemoveItem("damageBuffSpell", 1)

    Inventory: main
    - sword: 1

    Because the damageBuffSpell is no longer in your inventory, this is why you are getting a null reference the next time the method gets called. Inventory.main.GetItem("damageBuffSpell"); is returning null for scrollItem because there is no damageBuffSpell in main, and then two lines down in the debug.log where it says scrollItem.quantity, it's trying to access quantity of a null object.

    There is an onItemRemoved callback which gets called when the item gets removed from the inventory, and would get called after the second RemoveItem call finishes in the breakdown I included above (onItemQuantityChanged would get called after the first one finishes). You could use this to check for confirmation that the final remove worked (and take any other actions that you may want to take when an item is removed from an inventory). The callback unfortunately slipped through our inventory class documentation, but it works the same way as the one documented in the Wallet class: https://docs.unity3d.com/Packages/c...ityEngine_GameFoundation_Wallet_onItemRemoved

    I hope that all makes sense, if not, let me know, and thanks for taking a look at GameFoundation and letting us know how it's going!
     
    DemonFangZ likes this.
  10. DemonFangZ

    DemonFangZ

    Joined:
    Feb 6, 2019
    Posts:
    7
    So removing the last item would fall under the second case, where amountToRemove >= item.quantity .

    I believe I was incorrectly treating: quantity = 0 to be the same as the item no longer existing in the inventory. I was expecting the quantity value to change to zero, but it makes sense now why the quantity wouldn't be updated. As you mentioned, the local reference would still be pointing to the un-updated quantity, since the item has been removed from the inventory.

    Thanks @erika_d for the detailed clarification.
     
    erika_d likes this.
unityunity