I'm creating a system for equipping items to a player. I'm referencing this example for how to do write the CloudScript end of it. I've got the items equipping just fine, but I want to wrap this up by adding in my error handling (invalid item, item isn't owned, item is already equipped, etc).
The example I followed throws an exception when various things happen. One of them is for a null or missing argument:
if(args == null || typeof args.referralCode === undefined || args.referralCode === "") { throw "Failed to redeem. args.referralCode is undefined or blank"; }
This throws an exception which is all wrapped in a try/catch, ending with:
catch(e) { var returnObj = {}; returnObj["errorDetails"] = "Error: " + e; return returnObj; }
In the client code from the referenced example (ln 151), these exceptions appear to end up in result.Error:
if(result.Error != null) { Debug.LogError(string.Format("{0} -- {1}", result.Error, result.Error.Message)); return; }
I'm having trouble getting this to work in practice. My exceptions end up in the FunctionResult object instead of in the Error object.
Here's my CloudScript:
// Get an item from an array of items function GetItem(container, itemId) { for(var index in container) { if(container[index].ItemId === itemId) return container[index]; } return null; } // Equip an item to the current player. // Args: // itemId: the string item Id of the item to be equipped handlers.equipItem = function(args) { try { // Check to make sure args are correct if(args == null || typeof args.itemId === undefined || args.itemId == "") { throw "Failed to find item. args.itemId is undefined or blank."; } // Check if the player owns the item var getUserInventoryRequest = { PlayFabId: currentPlayerId }; var getUserInventoryResult = server.GetUserInventory(getUserInventoryRequest); var item = GetItem(getUserInventoryResult.Inventory, args.itemId); if(item == null) { throw "Player does not own this item."; } // Equip the item var updateUserReadOnlyDataRequest = { PlayFabId: currentPlayerId, Data: {} }; updateUserReadOnlyDataRequest.Data[item.ItemClass] = item.ItemId; var updateUserReadOnlyDataResult = server.UpdateUserReadOnlyData(updateUserReadOnlyDataRequest); log.info("Equipped Item '" + item.ItemId + "'' to Player '" + currentPlayerId + "'' in Slot '" + item.ItemClass + "'."); // Return success var returnObj = {}; returnObj["FunctionResult"] = "Successfully equipped Item."; return returnObj; } catch(e) { // Return failure var returnObj = {}; returnObj["errorDetails"] = "Error: " + e; return returnObj; } }
I then make the request in Unity like this:
public void EquipItem(string id) { var request = new ExecuteCloudScriptRequest() { FunctionName = "equipItem", FunctionParameter = new { itemId = id } }; System.Action<ExecuteCloudScriptResult> successHandler = delegate(ExecuteCloudScriptResult obj) { Debug.LogFormat("Success! Return: {0}, Error: {1}", obj.FunctionResult, obj.Error); }; System.Action<PlayFabError> errorHandler = delegate(PlayFabError obj) { // General error (execution) Toolbox.DialogWindow.ShowPlayFabError(obj); }; PlayFabClientAPI.ExecuteCloudScript(request, successHandler, errorHandler); }
My client-side logs:
Success! Return: {"errorDetails":"Error: Player does not own this item."}, Error: Success! Return: {"FunctionResult":"Successfully equipped Item."}, Error: Success! Return: {"errorDetails":"Error: Player does not own this item."}, Error:
I get the error properly, but not in the right place. In every case the error or success response ends up in the FunctionResult object and the Error object is always null. I could easily differentiate between the results, but I'd rather just have the errors end up in the Error object like they should. How do I have a CloudScript function return an error in ExecuteCloudScriptResult.Error?
I've also got a few small but closely related questions:
- Where do I view the CloudScript log created by log.info, log.debug, log.error, etc?
- Is there a specific test environment for working on CloudScript? I'd prefer not creating tons of small revisions if I can avoid it.