Sign In Register

How can we help you today?

Start a new topic
Answered

Simple Storage and Retrieval Explanation

I'm sure that I'm missing something that should be patently obvious, but after several hours of headscratching whilst reading over documentation, tutorials, and a variety of forum posts, I'm still at a loss for how to retrieve custom player variables. From all I've read, it would appear that I need to be making use of the Cloud Code section of the GameSparks interface, but so far I've only been able to use it to alter the values I wish to address, and I have yet to find how to simply access those values without changing them. Any advice would be greatly appreciated.

For reference, here is a quick example of the code I'm using to find the number of lives the player currently has. I have an Event configured with the shortcode of postLives, containing an attribute with the shortcode lives, set to be a Number with a default value of 5 and a default calculation of Count. In the Cloud Code for the event, I have the following code snippet:
Spark.getPlayer().setScriptData("lives", Spark.getData().lives);

 Then, on the Unity side, I'm using the following code:

int livesTemp = 3;
new LogEventRequest().SetEventKey("postLives").SetEventAttribute("lives", livesTemp).Send((getLives) =>
 {
	if(getLives.HasErrors)
	{
		Debug.Log("Failed to retrieve player lives from GameSparks! (GameSparksLogin)");
	}
	else
	{
	       Brains3Manager.instance.lives = (int)getLives.ScriptData.GetObject("postLives").GetNumber("lives");
	}
});

 This, of course, simply changes the value of "lives" from the default value of 5 to that of livesTemp, which is 3. Since I've gotten the hang of altering the values of these variables, what I need to know now is how I would go about simply retrieving the stored values without altering them.


Again, I'm sure that this should be a supremely simple matter and I'm positive that I'm just missing some vital piece of the puzzle. In all fairness, I've been awake far longer than is probably sane & that may well have something to do with it. That aside, I've been working very hard on converting my game from using Parse to GameSparks and really don't wish to be balked by such a minor misstep. Any advice would be greatly appreciated.


Best Answer

Hi Kenneth,


ScriptData can be a bit confusing... I can see in your code that you only have "Spark.getPlayer().getScriptData("lives");"


Which is correct, getScriptData will just cache whatever scriptData you are getting into a variable or access it to be used for something. To have it return in the response. You need to use something like:


 

var lives = Spark.getPlayer().getScriptData("lives");

Spark.setScriptData("lives", lives);

 

The reasoning for that is:


Certain objects, like a player or challenge have their own scriptData that you can set information on and this will get stored as part the document in the collection.


However, requests and responses also have their own scriptData that allows you to set information to those as well.


You must chose what information to be surfaced in the request or response, this lets you run complex algorithms in cloud code and have only the pertinent information return.


So after modifying your code to that above you should see:


 

{
 "@class": ".LogEventResponse",
 "scriptData": "lives" : 3
}
{
 "@class": ".LogEventRequest",
 "eventKey": "postLives"
}

 

Or something similar.


Shane


This is quickly becoming a huge nightmare. It's not even as if I'm trying to do anything impressive here; I'm just trying to store, update and/or retrieve data... I was having some difficulties getting the Player's current Level to update correctly (it worked fine in game, but the data did not persist, showing me that it wasn't being properly updated on the GameSparks side). In an attempt to test it further, I removed myself from the NoSQL player & externalAuthentication databases. Upon attempting to log back in via my game, I received "Nullable objects must have a value" errors from the sections of my code that made use of the GS Cloud Code, even though those entries have Default Values set in the Events section. I presume this would also happen to anyone who hadn't logged into the game before, which breaks everything.

While appearing user friendly at first glance, the GameSparks BaaS is, so far, incredibly complicated and extremely difficult to make use of. The documentation glosses over a few things without going into any great detail, and almost all of the examples are JSON queries which are only useful on the Test Harness. This is driving me bonkers! It shouldn't have taken me three days to figure out how to store and retrieve exceedingly simple pieces of data, and the solution to doing so certainly shouldn't have resulted in completely breaking my game.

Again, I'm not looking to do anything complicated here. I simply need a WebGL compatible BaaS that will allow me to store, update, and retrieve information at will. I appreciate that you have gone out of your way to set it up so that we can have Facebook integration out of the box, but I already had that covered previously. I appreciate that you have Leaderboard capabilities, but even that is something I had easily accomplished on my own prior to trying to make use of the GameSparks system. Essentially, all I need is to be able to create a few small entries on a database, update those entries when required, and get the information back out of them. Why, why, why does this require me to jump around and do a dozen different nonsensical things in a dozen different nonsensical places? I should be able to simply Set and Get the information. Forgive me for ranting, but this is truly maddening and more than a little bit frustrating, especially since I've got a nearly production ready game that I'm eager to publish once I can get the BaaS aspects functioning the way that they should.

Here's a brief list of the very, very few things that I'm trying to achieve here.
  • Player lives (int)
  • Player scores (int) by level
  • Player "stars" (int) by level
  • DataTime storage (string) for Lives timer
  • Player currency (int)
  • Player items count (int)
  • Leaderboards (which just needs to iterate through the above information for other players, honestly)


That's pretty much the lot of it. I need to store, update, and retrieve a small handful of strings and int values. Days into trying to make heads/tails of GameSparks, I find myself little further along than I was when I began, even after poring over the various tutorials and included documentation. If you've any advice or suggestions on how to go about simply storing, updating and retrieving simple data like this within your system, preferably without the need to pull my hair out, please let me know as soon as you can.


1 person likes this
Woohoo! That seemed to work just fine :) I'll quit spamming up the message boards now, haha. Have a terrific weekend!

 

Hi,


The "yourCustomId" field is only in here as an example, it will cause an error on any registration or authentication after the first player has been registered as "yourCustomId" has already been entered in the script.PlayerLives collection. You could replace this with your own custom generated ID or use the playerID to populate this field to avoid this.


Thanks,

Liam

Just a quick update. I've also tried the following Cloud Code, which just leads to Null references even though the values are clearly there in the NoSQL browser.
Spark.getPlayer().getScriptData("lives");

 

 

Answer

Hi Kenneth,


ScriptData can be a bit confusing... I can see in your code that you only have "Spark.getPlayer().getScriptData("lives");"


Which is correct, getScriptData will just cache whatever scriptData you are getting into a variable or access it to be used for something. To have it return in the response. You need to use something like:


 

var lives = Spark.getPlayer().getScriptData("lives");

Spark.setScriptData("lives", lives);

 

The reasoning for that is:


Certain objects, like a player or challenge have their own scriptData that you can set information on and this will get stored as part the document in the collection.


However, requests and responses also have their own scriptData that allows you to set information to those as well.


You must chose what information to be surfaced in the request or response, this lets you run complex algorithms in cloud code and have only the pertinent information return.


So after modifying your code to that above you should see:


 

{
 "@class": ".LogEventResponse",
 "scriptData": "lives" : 3
}
{
 "@class": ".LogEventRequest",
 "eventKey": "postLives"
}

 

Or something similar.


Shane

Wonderful, thanks for helping me get the cloud code portion straight. In order to actually retrieve the data from within a C# script in Unity, should I be using something along these lines?

 

new LogEventResponse().ScriptData("lives") =>

 I'm not at all sure how to format the request in order to retrieve the data instead of accidentally overwriting it as I had been doing with the LogEventRequest calls in the script above.

Another Cloud Code inquiry, if I may. I have a partitioned Leaderboard setup and working fine, however I also need to be able to retrieve data from this for the player, not just everyone who has an entry. The Event is setup to store Score (maximum), Stars (maximum) and is organized by Level (grouped). I have no trouble adding to or retrieving a set number of entries from the Leaderboard with the LeaderboardDataRequest function, but I'm unclear as to how I'd pull information for a single, specific user, such as the player.

I have tried adding Cloud Code similar what you'd recommended above, and thought that it might work as a simple LogEventRequest, however it's only returning "null" values for the Score, Stars, and Level variables. How would I go about retrieving Score and Stars values for a specific player and a specific Level value?

Here is the Cloud Code I've tried using with the above Event setup:
var score = Spark.getPlayer().getScriptData("score");
var stars = Spark.getPlayer().getScriptData("stars");
var level = Spark.getPlayer().getScriptData("level");
Spark.setScriptData("score", score);
Spark.setScriptData("stars", stars);
Spark.setScriptData("level", level);

 

 Hmm... Well, the Test Harness results are as you'd expected them to be:

{
 "@class": ".LogEventResponse",
 "scriptData": {
  "lives": 3
 }
}
{
 "@class": ".LogEventRequest",
 "eventKey": "postLives",
 "lives": 5
}

 but I've still no idea how to phrase things in Unity in order to retrieve the data. It's a bit frustrating that there are so many "Sets" and absolutely no "Gets", but I suppose that would be too easy, haha. In any case, if and when you have a moment, would you be so kind as to clue me in on the proper function call(s) and phrasings from the Unity side of things? Thanks again for your assistance.

Trial and error for the win! :) Here's the Unity code I used to finally get it to work for me (forgive the Brains3Manager.instance reference, it's my singleton Game Manager), posted here for anyone else who has similar trouble:
int livesTemp = 5;
new LogEventRequest().SetEventKey("postLives").SetEventAttribute("lives", livesTemp).Send((getLives) =>
{
	if(getLives.HasErrors)
	{
		Debug.Log("Failed to retrieve player lives from GameSparks! (GameSparksLogin)");
	}
	else
	{
		Brains3Manager.instance.lives = (int)getLives.ScriptData.GetInt("lives");
	}
});

 

 Thanks again for all of your assistance, Shane!

 

Hi Damien,

 

We have added you to the example project for this.


Thanks,

Liam

In the meantime, I've found an incredibly inefficient and inelegant workaround. I'm essentially looping through the first 1000 entries in the Leaderboard and looking for a match to the Player's name. Once the match is found, I grab the values I need. It works for the moment, but certainly isn't a solution I'd like to use in production, especially considering that my game may grow beyond 1000 players, in which case the odds of the entry ever being found at all diminish significantly. I'm sure you guys have a better solution, but at least I have something working temporarily, which frees me up to continue my conversion from Parse to GS. I look forward to your suggestions :) Thanks!

 

Kenneth,


I wonder would it be worth trying to hop on a Skype call.  I think there are a lot of things on the platform that could save you time ... scores, stars, levels etc don't have to be added to a players ScriptData in this way. The leaderboard & achievement system should do what you need without all of this especially with segments. Personally I would use one of the Currencies to maintain lives too.  


Let me know if you would like to sort out a Skype or something.


Regards,


John.

Hi John,

Sorry, I was in the midst of typing out that rather longwinded rant when you responded. I actually don't use Skype, or anything else other than email. I'm still using an ancient flip-phone that looks like a classic Star Trek communicator. I'm old and poor, lol. I saw an answer to one of the other forum posts here that suggested using the currency section for lives, and it makes a great deal of sense. I haven't yet figured out just how to go about setting up currencies yet, but that does sound like a viable option.

Again, my apologies for the above rant. I'm just incredibly flustered at the moment and can't believe how much difficulty I'm having with something that should be so incredibly simple. Thanks again for your assistance.

 

Hi,


Well its not supposed to be a nightmare and sorry if my last comment was a little mis-timed.  What you want is straight forward.  We will post the code here for you tomorrow for both Unity and anything on the GS side.


John.

Thank you, John. That would be unbelievably fantastic and would certainly help to set my poor frazzled brain at ease. I've a feeling I'm going to LOVE the GameSparks system once I get the general hang of it & I applaud you guys for all that you're trying to achieve with it. It's just a bit more complex and/or convoluted than I'd initially imagined and it's unlike any other system that I've ever used. Again, my sincerest apologies for going "off the rails" there, it's just been one of those weeks. I look forward to seeing your examples and think I'll step away from the keys for awhile and try to clear my head a bit. Have a fantastic evening!

 

Login to post a comment