Search Unity

  1. We are migrating the Unity Forums to Unity Discussions. On July 12, the Unity Forums will become read-only. On July 15, Unity Discussions will become read-only until July 18, when the new design and the migrated forum contents will go live. Read our full announcement for more information and let us know if you have any questions.

Question Update item instance data

Discussion in 'Cloud Code' started by Corva-Nocta, Feb 13, 2023.

  1. Corva-Nocta

    Corva-Nocta

    Joined:
    Feb 7, 2013
    Posts:
    801
    Alright, so I got the adding an item to inventory to work in cloud code, now I need to change the instance data. I've got this line of code:

    Code (csharp):
    1. const { InventoryApi } = require("@unity-services/economy-2.3");
    2.  
    3. module.exports = async ({ params, context, logger }) => {
    4.   const { itemId } = params;
    5.   const { projectId, playerId } = context;
    6.   const inventory = new InventoryApi(context);
    7.  
    8.   const updateItem = await inventory.updateInventoryItem( projectId, playerId, itemId,
    9.   {
    10.     instanceData:
    11.     {
    12.       "stat1": 21,
    13.       "stat2": 13
    14.     }
    15.   });
    16. }
    which isn't working. Its returning the error:

    Invocation Error
    ------------------------------
    RequiredError: Required parameter projectId was null or undefined when calling updateInventoryItem.

    {
    "message": "Required parameter projectId was null or undefined when calling updateInventoryItem.",
    "name": "RequiredError",
    "stackTrace": []
    }

    Which doesn't make a lot of sense to me. Why would my code not have the projectId built in when I run it? I'm running it in the test ode on the UGS dashboard, which adds items to a player's inventory, why am I geting this error when I try to update it?

    EDIT: I finally got it working! Here is the code for anyone else that might need the help
    Code (csharp):
    1. const { InventoryApi } = require("@unity-services/economy-2.3");
    2. module.exports = async ({ params, context, logger }) => {
    3.  
    4.   const { projectId, playerId } = context;
    5.   const inventory = new InventoryApi(context);
    6.  
    7.   const tsword = await inventory.getPlayerInventory({ projectId, playerId, inventoryItemIds: "TSWORD" });
    8.  
    9.    const updated = await inventory.updateInventoryItem({
    10.     projectId,
    11.     playerId,
    12.     playersInventoryItemId: tsword.data.results[0].playersInventoryItemId,
    13.     inventoryRequestUpdate: {instanceData:
    14.     {
    15.       "stat1": 43,
    16.       "stat2": 43
    17.     }}});
    18. }
     
    Last edited: Feb 20, 2023
  2. lsaeteurn

    lsaeteurn

    Joined:
    Jan 26, 2023
    Posts:
    93
    I think the problem here is exactly the same problem you had before. Your parameters are incorrect.

    Please refer to the CloudCode API:
    https://cloud-code-sdk-documentation.cloud.unity3d.com/economy/v2.4/inventoryapi#updateInventoryItem

    The function actually takes an InventoryApiUpdateInventoryItemRequest object not those individual parameters:

    const itemRequest = {
    projectId,
    playerId,
    itemId,
    { instanceData: { "stat1": 21, "stat2": 13 } }
    };

    const updateItem = await inventory.updateInventoryItem( requestParameters: itemRequest );
     
  3. Corva-Nocta

    Corva-Nocta

    Joined:
    Feb 7, 2013
    Posts:
    801
    That's the weird part though, I just copied the code that I had in the addItem script and just modified it for update item, so there shouldn't be the same issue with the projectId right?

    I did try the code you posted, but it is also giving me an error, this time in the editor before I even run it. It tells me that this line "{ instanceData: { "stat1": 21, "stat2": 13 } }" has an unexpected "{", I tried removing them in different ways to see what happens. I can remove 2 of them and the error goes away, but then an error shows up on the next line saying an unexpected ":". So I am really not sure what the problem is or where it is, or how to fix it properly.

    Code (csharp):
    1. const { InventoryApi } = require("@unity-services/economy-2.3");
    2.  
    3. module.exports = async ({ params, context, logger }) => {
    4.   const { itemId } = params;
    5.   const { projectId, playerId } = context;
    6.   const inventory = new InventoryApi(context);
    7.  
    8. const itemRequest = {
    9.     projectId,
    10.     playerId,
    11.     itemId,
    12.       instanceData: { "stat1": 21, "stat2": 13 }
    13.   };
    14.  
    15.   const updateItem = await inventory.updateInventoryItem(requestParameters: itemRequest);
    current error: Unexpected ":"
     
    Last edited: Feb 14, 2023
  4. Corva-Nocta

    Corva-Nocta

    Joined:
    Feb 7, 2013
    Posts:
    801
    Here is what I am working with now, and the associated errors

    Code (csharp):
    1. const { InventoryApi } = require("@unity-services/economy-2.3");
    2.  
    3. module.exports = async ({ params, context, logger }) => {
    4.   const { projectId, playerId } = context;
    5.   const inventory = new InventoryApi(context);
    6.  
    7.   const tsword = await inventory.getPlayerInventory({projectId, playerId, inventoryItemIds : "TSWORD"});
    8.   if (tsword.data.results.length > 0)
    9.   {
    10.     //we have the sword
    11.     await inventory.updateInventoryItem(projectId, playerId, {playerInventoryItemId: "TSWORD", instanceData:
    12.     {
    13.         "stat1": 13,
    14.         "stat2": 13
    15.     }});
    16.   }
    17. }
    Error:
    Invocation Error
    ------------------------------
    RequiredError: Required parameter projectId was null or undefined when calling updateInventoryItem.

    {
    "message": "Required parameter projectId was null or undefined when calling updateInventoryItem.",
    "name": "RequiredError",
    "stackTrace": []
    }


    and then this version

    Code (csharp):
    1. const { InventoryApi } = require("@unity-services/economy-2.3");
    2.  
    3. module.exports = async ({ params, context, logger }) => {
    4.   const { projectId, playerId } = context;
    5.   const inventory = new InventoryApi(context);
    6.  
    7.   const tsword = await inventory.getPlayerInventory({projectId, playerId, inventoryItemIds : "TSWORD"});
    8.   if (tsword.data.results.length > 0)
    9.   {
    10.     //we have the sword
    11.     const itemRequest = {projectId, playerId, playerInventoryItemId: "TSWORD", instanceData:
    12.     {
    13.       "stat1": 21,
    14.       "stat2": 13
    15.     }};
    16.     const updateItem = await inventory.updateInventoryItem(requestParameters: itemRequest);
    17.   }
    18. }
    Error:
    Compilation Error
    ------------------------------
    SyntaxError: Unexpected token ':'

    UpdateItem.js:16:76


    (I also tried a similar version to this that changed the inventory.updateInventoryItem() to inventory.updateInventoryItem({}) which did make the syntax errors go away, but then gives me the same error as the first example where the projectId isn't set)

    I also tried this:

    Code (csharp):
    1. const { InventoryApi } = require("@unity-services/economy-2.3");
    2.  
    3. module.exports = async ({ params, context, logger }) => {
    4.   const { projectId, playerId } = context;
    5.   const inventory = new InventoryApi(context);
    6.  
    7.   const tsword = await inventory.getPlayerInventory({projectId, playerId, inventoryItemIds : "TSWORD"});
    8.   if (tsword.data.results.length > 0)
    9.   {
    10.     //we have the sword
    11.  
    12.     const playersInventoryItemId = tsword.data.playersInventoryItemId;
    13.     await inventory.updateInventoryItem(projectId, playerId, playersInventoryItemId, { instanceData: {
    14.         "stat1": 23,
    15.         "stat2": 23
    16.      }
    17.    });
    18.   }
    19. }
    but that also says the projectId isn't set (same error as the first) beginning to think there's a problem with projectId somehow.

    everything works just fine in the script except for the updating of instance data. That's the only hole I have left
     
    Last edited: Feb 14, 2023
  5. Corva-Nocta

    Corva-Nocta

    Joined:
    Feb 7, 2013
    Posts:
    801
    Ok I think I got even closer, but still an error. I found that I need to add "inventoryRequestUpdate:" to the code, and I swear I've seen that somewhere in the documentation that shows that line, but I can't find it anywhere I look. If anyone knows where this is located please share! Here's where I'm at right now:

    Code (csharp):
    1. const tsword = await inventory.getPlayerInventory({ projectId, playerId, inventoryItemIds: "TSWORD" });
    2. const updated = await inventory.updateInventoryItem({ projectId, playerId, playersInventoryItemId: {inventoryItemId: "TSWORD"}, inventoryRequestUpdate: {instanceData:
    3.     {
    4.       "stat1": 43,
    5.       "stat2": 43
    6.     }}});
    currently giving me Error: Request failed with status code 400

    Easier to read version of the same code:
    Code (csharp):
    1. const tsword = await inventory.getPlayerInventory({ projectId, playerId, inventoryItemIds: "TSWORD" });
    2. const updated = await inventory.updateInventoryItem({
    3.     projectId,
    4.     playerId,
    5.     playersInventoryItemId: {inventoryItemId: "TSWORD"},
    6.     inventoryRequestUpdate: {instanceData:
    7.     {
    8.       "stat1": 43,
    9.       "stat2": 43
    10.     }}});
     
    Last edited: Feb 15, 2023
  6. lsaeteurn

    lsaeteurn

    Joined:
    Jan 26, 2023
    Posts:
    93
  7. Corva-Nocta

    Corva-Nocta

    Joined:
    Feb 7, 2013
    Posts:
    801
    Ah yeah, that explains why it didn't work just from copy paste haha.

    Unfortunately javascript is still like a foreign language to me, the syntax is very odd to me. I only really know C#, I mean the logic is roughly exactly the same, but the syntax and how to find it is a bit different. I definitely appreciate the link you sent with the syntax, it just sucks that I can't really read it yet haha. But I think I am getting closer to the answer, pouring over the documentation, other posts, and the example projects is getting me just about there. I think I just need one last little part of the code to be done correctly to get it right, but I don't yet know which part of the code is wrong. The last post I did on this thread has me just about there, just gotta find that last missing piece. The search continues!
     
  8. lsaeteurn

    lsaeteurn

    Joined:
    Jan 26, 2023
    Posts:
    93
    Their documentation is confusing because their examples are mostly referring to the Economy API for Unity. There are actually 3 Economy APIs and each of them are different: Unity (C#), REST APIs, and CloudCode API (JS).

    It took me a bit to figure this out as well. On top of that, you have to learn some basic JS syntax.

    Since you are working in the CloudCode environment, you need to look at the CloudCode API for Economy:
    https://cloud-code-sdk-documentatio...y/v2.4/inventoryapiupdateinventoryitemrequest
     
  9. Corva-Nocta

    Corva-Nocta

    Joined:
    Feb 7, 2013
    Posts:
    801
    Yeah there's a lot to learn there. And learning a new syntax sucks! But it's not the worst, I am slowly figuring it out.

    That link did help more than the other one! But it appears what that link says I need, I currently have in my code. So I am not sure what is wrong. I have all the components it says I should have, but I guess it's not compiled exactly right so it doesn't work. And the errors I get aren't exactly helpful.

    Just wish there was an example somewhere, anywhere, of how to do the updating of instance data that actually works. The only example I've been able to find anywhere is a poat here on the forums, but I tried using the same code and it doesn't work. So I'm a bit lost here on something that feels like it should be pretty simple.
     
  10. lsaeteurn

    lsaeteurn

    Joined:
    Jan 26, 2023
    Posts:
    93
    Because the examples expect you to know some JS, JSON, and REST APIs. One thing to keep in mind with Javascript is that everything is actually a dictionary and JSON is actually an object in JS. To add a field to an object (JSON), you just simply assign it dynamically: instanceData.xp = 120;

    When you print out the value of an object, you'll see that it spits out JSON.

    Here's how I'm updating instance data:
    Code (JavaScript):
    1. const expiration = Math.floor(Date.now() / 1000) + 5 * 60;
    2. const playersInventoryItemId = "SWORD";
    3. const inventoryRequestUpdate = { instanceData: { count: 10, expiration: expiration } };
    4. await economy.updateInventoryItem({ projectId, playerId, playersInventoryItemId, inventoryRequestUpdate });
     
  11. Corva-Nocta

    Corva-Nocta

    Joined:
    Feb 7, 2013
    Posts:
    801
    I think that makes sense. It at least gives me a better idea of how it works. Very good too know about the dictionary and JSON setup! That will l likely come in handy later.

    I made a few minor adjustments to the code, and now I seem to be getting the error that the item can't be found... I cqn definitely verify I have the item. Have you ever encountered this?

    Here's the whole code, which shows how I know I have the item too:

    Code (csharp):
    1. const { InventoryApi } = require("@unity-services/economy-2.3");
    2. module.exports = async ({ params, context, logger }) => {
    3.   const { projectId, playerId } = context;
    4.   const inventory = new InventoryApi(context);
    5.  
    6.   const tsword = await inventory.getPlayerInventory({ projectId, playerId, inventoryItemIds: "TSWORD" });
    7.  
    8.   if (tsword.data.results.length > 0) {
    9.     //we have the sword
    10.     const updated = await inventory.updateInventoryItem({
    11.     projectId,
    12.     playerId,
    13.     playersInventoryItemId: "TSWORD",
    14.     inventoryRequestUpdate: {instanceData:
    15.     {
    16.       "stat1": 43,
    17.       "stat2": 43
    18.     }}});
    19.   } else {
    20.     //We do not have the sword
    21.     const createdSword = await inventory.addInventoryItem({ projectId, playerId, addInventoryRequest:
    22.     {
    23.         inventoryItemId: "TSWORD",
    24.         instanceData: {
    25.           "stat1": 40,
    26.           "stat2": 90
    27.         }
    28.       }
    29.     });
    30.   }
    31. }
    as you can see, I can only run the update request if we know the player has the item, so I shouldn't have an error saying it can't find the item
     
    Last edited: Feb 20, 2023
  12. lsaeteurn

    lsaeteurn

    Joined:
    Jan 26, 2023
    Posts:
    93
    The playersInventoryItemId is not the same id as the item ID (as stated in the docs). It is randomly generated if not specified.

    You can get it from the player's item that you already requested:
    tsword.data.results[0].playersInventoryItemId

    Or, you can set it to the same as the item ID when you first add it:
    Code (JavaScript):
    1. const addInventoryRequest = { inventoryItemId: "TSWORD", playersInventoryItemId: "TSWORD" };
    2. await economy.addInventoryItem({ projectId, playerId, addInventoryRequest });
     
    Last edited: Feb 20, 2023
  13. Corva-Nocta

    Corva-Nocta

    Joined:
    Feb 7, 2013
    Posts:
    801
    Oh! Duh I should have noticed that lol. But that does make sense, I am grabbing the specific item in the inventory, then I need to modify that specific item. Not just an item with that name.

    That code snippet worked! I can finally update instance data! I greatly appreciate all the help you have given, both with actual code and understanding the concepts. I'll post my final code for anyone else that might need it:

    Code (csharp):
    1. const { InventoryApi } = require("@unity-services/economy-2.3");
    2. module.exports = async ({ params, context, logger }) => {
    3.   const { projectId, playerId } = context;
    4.   const inventory = new InventoryApi(context);
    5.   const tsword = await inventory.getPlayerInventory({ projectId, playerId, inventoryItemIds: "TSWORD" });
    6.   if (tsword.data.results.length > 0) {
    7.     //we have the sword
    8.     const updated = await inventory.updateInventoryItem({
    9.     projectId,
    10.     playerId,
    11.     playersInventoryItemId: tsword.data.results[0].playersInventoryItemId,
    12.     inventoryRequestUpdate: {instanceData:
    13.     {
    14.       "stat1": 43,
    15.       "stat2": 43
    16.     }}});
    17.    
    18.   } else {
    19.     //We do not have the sword
    20.     const createdSword = await inventory.addInventoryItem({
    21.       projectId,
    22.       playerId,
    23.       addInventoryRequest:
    24.       {
    25.         inventoryItemId: "TSWORD",
    26.         instanceData:
    27.         {
    28.           "stat1": 40,
    29.           "stat2": 90
    30.         }
    31.       }
    32.     });
    33.   }
    34. }
     
  14. lsaeteurn

    lsaeteurn

    Joined:
    Jan 26, 2023
    Posts:
    93
    In my game, the player's item id is the same as the item's id because they won't be adding more than 1 instance of an item. I just simply increment the count value of the Instance data if the item already exists. This may be different from your use case.
     
    Corva-Nocta likes this.