Sign In Register

How can we help you today?

Start a new topic
Answered

save event with array in Unity

Hello.

I'm a complete noob in GS, so forgive me if my question might sound too simple.

I've followed the tutorial on how to store a ghost race replay and it works fine. This is exactly what I need. Unfortunately, the tutorial stops right before the last step: save the data (and load it) from inside a C# script.


Browsing the web I found something and I could make this, that works neatly:


 

		LogEventRequest request = new LogEventRequest();
		request.SetEventKey ("STORE_RACE_DATA");
		request.SetEventAttribute ("GHOST_DATA", jsonString);
		request.SetEventAttribute ("TRACK_NUMBER", DataController.dataController.currentRaceData.GetLevelNumber());
		request.SetEventAttribute ("RACE_TIME", Round1000 (DataController.dataController.currentRaceData.GetFinalTime()));
		request.SetEventAttribute ("STARSHIP_NUMBER", DataController.dataController.data.GetActiveStarhip());

		request.Send ((response) => {
			if (!response.HasErrors)
				Debug.Log ("added");
			else
				Debug.Log ("error " + response.Errors.JSON);
		});

The data structure I have is very similar to the one of the tutorial:

TRACK_NUMBER, RACE_TIME, STARSHIP_NUMBER are Numbers, while GHOST_DATA is of type JSON.

Here is where I have the trouble: GHOST_DATA is an array and if I create the Json string it is interpreted as a simple string. How could I save the array in GHOST_DATA?


I hope I was clear, thanks for any possible future help.



Best Answer

 Hey Beppi,

Running your 'GRD' event in the test harness works fine for me and im getting responses back without any problems.

I'm guessing you are using unity, so i've checked the call there too, and the data is coming back in the response there too (but it is very temperamental with that encoded string because some of them are very long).
--> See first Pic

So, i assume you are having problem on the 'unity' end getting the data out?
I have a solution for you to try, but that ghostData element is not going to play nice unless you have something special on your side to parse it, its just too long

 

new GameSparks.Api.Requests.LogEventRequest()
			.SetEventKey("GRD")
				.SetEventAttribute("TN", "0")
					.SetEventAttribute("ST", "3")
						.SetDurable(true)
							.Send((response) => {

					// get all the objects in the response script data, this is each race that met the event attributes you requested //
					// When you sent the scriptdata back in CloudCode, you named it "selectedData", so this helps us get specifically that data//
					List<object>  dataList = response.ScriptData.GetObjectList("selectedData"); 
					// now we can iterate through each element as if it is a dictionary, just use the key and get each item //
					foreach (Dictionary<string, object> raceData in dataList) 
					{
						// each of these are converted to a string since we dont know exactly whats in each element at this stage //
						string nickName = raceData["nickName"].ToString();
						int trackNo = int.Parse(raceData["trackNumber"].ToString());
						int starShipNumber = int.Parse(raceData["starshipNumber"].ToString());
						int timeTaken = int.Parse(raceData["timeTaken"].ToString());
						long raceDate = long.Parse(raceData["raceDate"].ToString()); // need to check the date-format here so it can be parsed //
						string playerID = raceData["playerId"].ToString();

						object ghostData = raceData["ghostData"]; // just save this as a object for now

						// Just print these 
						print("Nick Name: "+nickName);
						print ("Track Number: "+trackNo);
						print ("Ship Number: "+starShipNumber);
						print ("Time Taken "+timeTaken+"s");
						print ("Date: "+raceDate);
						print ("Player ID: "+playerID);
					}

				});

 

You can see the result of this call in the second picture, along with the json-data received in the response.

I hope that helps?
If you still need help adding the array data instead of the encrypted string, please let me know.

Sean
Untitled2.png
(90.5 KB)
Untitled.png
(69.5 KB)

I got no answers and hence I did it by myself.

I simply transformed the array into an encoded string, and flattened it all to make it easier to work with.

Anyway I still have a zillion of continuous problems that always end with painful hours of search and trial/error frustrating sessions, just to understand a syntax or how to do a simple thing... any help?

Thank you.

It's three days now that I'm trying to do the simplest thing:

I have my data stored, I have created the "get" event, i receive an empty request response, and...? now? should I use ScriptData? Should I use "ToString()" to get the strings? Should I get it as JSON and interpret it on the client? how and where do I use the setScriptData parameter that I wrote in the CloudCode, I don't understand why I should use script Data as soon as I'm retrieving normal data and not "extra data".

All documentation seems well done, then as soon as you try to dig into it you are left with dozens of questions, and tutorials magically end one step before answering those questions.

Can some one help me, or should I move to Parse?

 Hey Beppi,

Sorry about the delay getting to your question, i should be about to help you sort this out. I'm going to take a look at your event now.

Sean



Thank you very much,


I finally succeeded in getting the data with this, is this the correct way?

 

	public void LoadReplayFromServer() {  // TODO
		Debug.Log("Load Replay From Server");

		string raceData, nickName;
		int? starshipNumber, timeTaken;

		LogEventRequest request = new LogEventRequest();
		request.SetEventKey ("GRD")
				.SetEventAttribute ("TN", DataController.dataController.currentRaceData.GetLevelNumber())
				.SetEventAttribute ("ST", Constants.constants.starshipCharacteristics[DataController.dataController.currentRaceData.starshipType].GetTier());

		request.Send ((response) => {
			if (response.HasErrors) {
				Debug.Log("FAIL with error " + response.Errors.JSON);
			} else {
				string json = response.ScriptData.JSON;
				Debug.Log (json);
				var N = SimpleJSON.JSON.Parse(json);

				raceData = N["selectedData"][0]["ghostData"].Value;
				nickName = N["selectedData"][0]["nickName"].Value;
				starshipNumber = N["selectedData"][0]["starshipNumber"].AsInt;
				timeTaken = N["selectedData"][0]["timeTaken"].AsInt;
			}
		});
	}

 Using this utility:

http://wiki.unity3d.com/index.php/SimpleJSON


I got no success in any way using GetString() and other methods that wouldn't force me to pass through a JSON.


How is the data transmission performed? does it transfer a JSON or does it transfer binary compressed data and then transformed in JSON on client-side?

Thanks.

Answer

 Hey Beppi,

Running your 'GRD' event in the test harness works fine for me and im getting responses back without any problems.

I'm guessing you are using unity, so i've checked the call there too, and the data is coming back in the response there too (but it is very temperamental with that encoded string because some of them are very long).
--> See first Pic

So, i assume you are having problem on the 'unity' end getting the data out?
I have a solution for you to try, but that ghostData element is not going to play nice unless you have something special on your side to parse it, its just too long

 

new GameSparks.Api.Requests.LogEventRequest()
			.SetEventKey("GRD")
				.SetEventAttribute("TN", "0")
					.SetEventAttribute("ST", "3")
						.SetDurable(true)
							.Send((response) => {

					// get all the objects in the response script data, this is each race that met the event attributes you requested //
					// When you sent the scriptdata back in CloudCode, you named it "selectedData", so this helps us get specifically that data//
					List<object>  dataList = response.ScriptData.GetObjectList("selectedData"); 
					// now we can iterate through each element as if it is a dictionary, just use the key and get each item //
					foreach (Dictionary<string, object> raceData in dataList) 
					{
						// each of these are converted to a string since we dont know exactly whats in each element at this stage //
						string nickName = raceData["nickName"].ToString();
						int trackNo = int.Parse(raceData["trackNumber"].ToString());
						int starShipNumber = int.Parse(raceData["starshipNumber"].ToString());
						int timeTaken = int.Parse(raceData["timeTaken"].ToString());
						long raceDate = long.Parse(raceData["raceDate"].ToString()); // need to check the date-format here so it can be parsed //
						string playerID = raceData["playerId"].ToString();

						object ghostData = raceData["ghostData"]; // just save this as a object for now

						// Just print these 
						print("Nick Name: "+nickName);
						print ("Track Number: "+trackNo);
						print ("Ship Number: "+starShipNumber);
						print ("Time Taken "+timeTaken+"s");
						print ("Date: "+raceDate);
						print ("Player ID: "+playerID);
					}

				});

 

You can see the result of this call in the second picture, along with the json-data received in the response.

I hope that helps?
If you still need help adding the array data instead of the encrypted string, please let me know.

Sean
Untitled2.png
(90.5 KB)
Untitled.png
(69.5 KB)
Sorry Beppi, i didn't see that last post in time.

Glad to see you got it working.
There isn't really a 'right' way to get the data out, it really depends on what you are most comfortable with.
I just like to use the GetObjectList() method because it is super-handy to iterate through a dictionary to get the elements i need.

Sean

 

Thank you very much, I'll check your solution, anyway. The string is very long because it contains an encoded replay. At a first glance I set it as an array, like in the tutorial https://docs.gamesparks.net/howtos/cloud-data/how-to-implement-data-sharing.

then I was not able to retrieve that complex JSON object (although now, after all this work, probably I would be able), and turned on an encoded string, that BTW takes about 1/5 of the space of a JSON array. For that reason I was asking if the transfer on the network is compressed and binary: 40KB can be a problem on some low bandwidth mobile device.

It is sent over websockets as plaintext, but the limit is around 130k for the response, so you should be okay.

 

Hi Beppi,

Apologies for the delay in getting your answer to you, we know it can be frustrating trying to find a solution to a problem especially if it takes a few days.

I just thought I would pop in and say that our customer support team operate from Monday to Friday 9am - 5:30pm UTC+01:00 so they would not have seen your post until yesterday morning. The customer support team during these hours will be browsing the forums trying to help in any way they can.

For certain issues it is recommended that you open a support ticket here, especially if it is an urgent issue. If it is an emergency then it is escalated to tech support who are notified even on weekends (note these are rare cases like outages or critical errors etc). The goal for the forums is to create a community where developers help other developers which a lot of people have been doing but we still help out like we have done here.

Apologies again for the delay again but it is worth noting that outside of office hours it will be rare to get an answer in our forums from customer support and even a lot of our community may not work on weekends.

Hope this helps,
Kind Regards,
Jamie


 

Dear Jamie,

apologies are mine for having been maybe too urgent in my requests, no problem.

Sean has been very clear and kind, making all his efforts to help me. Thank him from me. And you are too.

Anyway I think that the major problem is not in your assistance that obviously depends from office hours, but on documentation, that is always on no matter whata you do, due to the fact that the often people (like me) that come to this service are not experts of mongodb, javascript and all the technology that you created. But unfortunately documentation looks like it has written by people that already know so many things around that are not necessarily clear.


For example: I've been banging my head for hours now. I want to retrieve a single element by a single cursor derived from a single query on my mongodb, and use it in another query to return additional information. The idea is to send to the user that requested a race replay, also the fbId of his opponent and if the opponents wants his picture to be displayed.

Probably it's a trivial operation, but I've been here since hours. In sql I would have written it in 1 line of code. My fault, and I'm now studying mongodb, but Gamesparks unfortunately doesn't help in this process, the training curve is sloooow: people could abandon before the fight, not me.

These are the questions that arose:

- how do I get a single value by a cursor. I want to get just the "playerId" value from the raceData I received. I did it but I keep on receiving "null" errors from javascript. The execution of 

var oppId = selectedData.curr().get("playerId");

 fails saying selectedData.curr() is null.


- I don't understand, once I will have the oppId that I'm desperately trying to get, if I am allowed to do something like this: 

Spark.setScriptData("selectedData", selectedData);
Spark.setScriptData("oppId", oppId);

 and receive both the information on the client side.


- I didn't undersand how to have the Cloud Code write on a console, so that I can fastly test locally.


I'm sure that all this information is available, or just obvious, unfortunately I'm still banging my head... :((


Thank you


I just wanted to say that I don't feel like opening a ticket just because your service works wonderfully, it's just me, not you :D :D

Save the head-banging for the mosh-pit Beppi, i'll take a look at this for you now


-Sean

Here I am Sean.

I think I understood one thing, tell me if it's correct. I cannot access opponents Data because I access as user that is not a opponent's friend. Is it correct?

Anyway basically what I want is to be able to retrieve the playerId from the replay (that is opponent's id) and send to the client these information:

- boolean if the user wants to display the picture

- facebook picture or facebook id


Please tell me if you prefer to use a different media to talk as soon as the forum might be too slow. Thank you.

Yes, thats correct.
So it sounds like we need to sort out a way to update the race-data with the id of any player who enters?
Is the playerID you store in the raceData the opponent's id or the current user's id?

How do you link two users into a race?
It would be simplest to add user data into the raceData when they join, then you can access it afterwards.


 

Login to post a comment