I'm starting incorporating GameSparks into my application, but am a bit stuck very close to shore.
Let's say I am retrieving the account details as so:
public class Test : MonoBehaviour {
public string playerName;
public Text showName;
void GetPlayerName()
{
new AccountDetailsRequest().Send((response) => {
playerName = response.DisplayName;
Debug.LogWarning("Playername is " + playerName); //Debug 1
});
Debug.LogWarning("Playername is " + playerName); //Debug 2
}
void printName()
{
GetPlayerName()
showname.Text = "Hello, "+playerName;
Debug.LogWarning("Trying to show the name on screen"); //Debug 3
}
When I run the script above, Debug 2 is executed first and returns "Player name is: ". Then Debug 3 is executed and the text component shows "Hello, ". Then Debug 1 is executed showing "Player name is: Whatever".
If I then run the script again, all Debugs show the name and the name is displayed on screen.
Why is this?
Even if I put AccountDetailsRequest() and assigning the name to the text compononent in the same method, the behaviour is the same.
This happens with all the GS API calls (be it this or LogEventRequest, or whatever) of course.
How could I both get the information and display the variable on screen with only one call.
I'm sure it is something simple, but I've been looking up and down the forum and internet and can't find an explanation for this.
Understanding this will allow me to apply the same knowledge to all the other API calls.
Best Answer
C
Customer Support
said
about 6 years ago
Hi Alex,
This is due to the asynchronous nature of requests. We can not always predict with certainty the time at which the response is received. This leaves the potential for us to attempt to refernce data that has not yet been acquire. It is for this reason that we use callbacks when utilizing asynchronously acquired data.
Here is an example of funciton I use with callbacks that run when the data I want to use is received:
public delegate void OnGetBestScoreSuccess(int score);
public delegate void OnError(string errorCode);
public void GetBestScore(OnGetBestScoreSuccess onSuccess, OnError onError)
{
var leaderBoardList = new List<string> {"highScoreLeaderBoard"};
new GetLeaderboardEntriesRequest()
.SetLeaderboards(leaderBoardList)
.Send((response) =>
{
foreach (var t in leaderBoardList)
{
if (!response.HasErrors)
{
if (response.BaseData.GetGSData(t).GetNumber("rank") != null)
{
int bestScore = (int) response.BaseData.GetGSData(t).GetNumber("score");
onSuccess(bestScore);
}
else
{
{
onError("Error in acquiring lb data");
}
}
}
else
{
{
onError("Error in response");
}
}
}
});
}
Here is how I called this function in another class. It's worth noting that I sued lambdas to assign anonymous functions as arguments.
This is due to the asynchronous nature of requests. We can not always predict with certainty the time at which the response is received. This leaves the potential for us to attempt to refernce data that has not yet been acquire. It is for this reason that we use callbacks when utilizing asynchronously acquired data.
Here is an example of funciton I use with callbacks that run when the data I want to use is received:
public delegate void OnGetBestScoreSuccess(int score);
public delegate void OnError(string errorCode);
public void GetBestScore(OnGetBestScoreSuccess onSuccess, OnError onError)
{
var leaderBoardList = new List<string> {"highScoreLeaderBoard"};
new GetLeaderboardEntriesRequest()
.SetLeaderboards(leaderBoardList)
.Send((response) =>
{
foreach (var t in leaderBoardList)
{
if (!response.HasErrors)
{
if (response.BaseData.GetGSData(t).GetNumber("rank") != null)
{
int bestScore = (int) response.BaseData.GetGSData(t).GetNumber("score");
onSuccess(bestScore);
}
else
{
{
onError("Error in acquiring lb data");
}
}
}
else
{
{
onError("Error in response");
}
}
}
});
}
Here is how I called this function in another class. It's worth noting that I sued lambdas to assign anonymous functions as arguments.
I hope this answers your question. Let me know if you need further clarification on anything.
Best Regards, Patrick.
A
Alex Catana
said
about 6 years ago
Hello Patrick!
Wow!! Many thanks for your super fast reply.
While I'm sure the example you gave works and is the right way of doing things, it is a bit too advanced for me to follow at this point, I'm afraid. I'm still getting to grips with integrating GameSparks into Unity and the API calls, etc.
I usually learn and understand things by following examples...I take the example, implement it in my test app and see the result and try to make sense of it (99% of the time succesfully). But your example has references to things that are specific to your application and it confuses me a bit :).
Is there any chance that a simplified more generic example can be used? Maybe with how this would be implemented with the AccountDetailsRequest() call (cause this is as generic as it gets)?
It's the flow of things that I ultimately want to get from the example...
many thanks in advance for your time!
Alex
A
Alex Catana
said
about 6 years ago
Hello Patrick! I have replied to your comment about an hour ago...but it hasn't appeared yet. Testing with this to see if it appears
A
Alex Catana
said
about 6 years ago
Trying to reply again.
Many thanks for your prompt reply earlier.
However, because I'm still getting to grips with everything, the example is a bit too advanced for me. I usually learn by testing snippets in my test app, seeing the results and trying to make sense of everything (which works 99% of the time). But your example has bits that are specific to your app which I can't replicate... Lambdas is also something I have yet to learn so that doesn't help either :).
Any chance a more generic example can be used? Something that might use AccountDetailsRequest()? Like just simply requesting the displayName or currency1 amount, storing it in a variable and updating a text component with it (or just printing to console). A simplified example of a callback, so to speak. And once i am up to speed with the more advanced elements in C#/JS, I can expand it myself..
I now understand why what I was trying to do doesn't work, but still looking for a way to work around that.
Many thanks,
Alex
Customer Support
said
about 6 years ago
Hey Alex Catana,
Lamdas allow you to invoke logic without defining a function. Essentially it is just inline function declaration.
You will have to use a delegate or lamda to expose the response for any GameSparks Request. Rather than using callbacks you can place a null check within the response and then pass the value to your function as an argument. That may look something like this:
(response) => { if(response.value != null)
{ MyFunction(response.value); } }
Does this make sense?
Best Regards, Patrick.
Customer Support
said
about 6 years ago
Hi Alex,
I can understand that. Hes a working example. In this function, I send a Registration Request. Based on the response it returns, either our Registration was successful, failed, or failed due to the player already existing. In the latter case, we instead perform an Authentication request with the credentials provided.
public void AuthenticatePlayer(string displayName, string password)
{
new RegistrationRequest() // Attempt to Register a New Player
.SetDisplayName(displayName) // Set Display name
.SetUserName(displayName) // Set User Name
.SetPassword(password) // Set Password
.Send((regResponse) => {
if(!regResponse.HasErrors)
{
Debug.LogWarning("Registration Succesful");
SceneManager.LoadScene("GeometryJump");
}
else
{
if(!(bool)regResponse.NewPlayer) // If an Existing Player, use Auth instead
{
Debug.LogWarning("Existing Player, Switching to Auth");
new AuthenticationRequest() // Attempt to Authenticate Existing Player
.SetUserName(displayName) // Set UserName
.SetPassword(password) // Set Password
.Send((authReponse) => { // In Line Reference to Asynchronous Response
if(!authReponse.HasErrors) // If no Errors in Repsonse
{
Debug.Log("Authentication Succesful");
SceneManager.LoadScene("GeometryJump");
}
else // If Errors in Response
{
Debug.Log("Error Authenticating Player " + authReponse.Errors.JSON); // Log errors
}
});
}
}
});
}
Does this clear things up for you? Happy to assist further !
Best Regards, Patrick.
A
Alex Catana
said
about 6 years ago
Hi Patrick.
Once again, many thanks for your reply. I actually managed to put the above together by myself from studying the documentation and this bit works as indended! Why I started this topic is...From here I want to retrieve a parameter from the response (i.e. the username or the displayName) and store it in a local variable for other operations.
Assuming the local variable is "myLocalVariable"... I have been trying to assign authResponse.displayName (for example) and then print myLocalVariable to the console. I need this to happen when I call "AuthenticatePlayer(displayName,password);" from another method or from the editor.
But no matter where I put "myLocalVariable=authResponse.displayName" and the "Debug.Log("Name: "+myLocalVariable) it always prints just "Name: ". For example, if i put Debug.Log between lines 35 and 36 in your code, the program seems to run Debug.log first and then assign the value. I have to call it a second time for it to print to console correctly. The way I see it, it executes everything outside the "new RegistrationRequest..." bit (whether is above or below) and then it moves on to actually executing the API call. It doesn't execute in order from top to bottom. Again, I've moved these up and down the method without success.
I hope I am making sense. Your help so far has been great and very much appreciated.
Customer Support
said
about 6 years ago
hi Alex,
So a couple of things could be happening here, presuming there are no errors in the response or otherwise.
It may be that you are assigning the variable correctly but that it does not have the appropriate scope for where you are attempting to debug it.
If you look at this example, you can see where I have placed a debug referencing the displayName:
new AuthenticationRequest() // Attempt to Authenticate Existing Player
.SetUserName(displayName) // Set UserName
.SetPassword(password) // Set Password
.Send((authReponse) => { // In Line Reference to Asynchronous Response
if(!authReponse.HasErrors) // If no Errors in Repsonse
{
Debug.Log("Authentication Succesful" + authReponse.DisplayName);
}
else // If Errors in Response
{
Debug.Log("Error Authenticating Player " + authReponse.Errors.JSON); // Log errors
}
});
In my test, it succesfully logs my display name to the console.
Hope this helps.
Best Regards, Patrick.
A
Alex Catana
said
about 6 years ago
That is correct Patrick! It does indeed print it to console if you are printing the display name received in the response directly. But this also needs to be assigned to a string variable in the application for other operations.
So the Debug.Log which I'm having problems with is the one that outputs the value of the variable which was passed the authReponse.DisplayName.
So with a button click I want to call "AuthenticationRequest()", assign the "authReponse.DisplayName" to a myVariable string and print Debug.Log("Display name is: "+ myVariable); all in one go. At the moment I have to click the button twice for this to happen. The first time it prints "Display name is: " and the second time it displays correctly.
This leads me to believe that Debug.Log("Display name is: "+ myVariable); is executed first and then the "AuthenticationRequest()". I have tried putting the Debug.Log in various places in the method, but it still gets executed first.
I'm sure it's something simple and stupid...but can't figure it out.
Alex
A
Alex Catana
said
about 6 years ago
UPDATE
I spent all day today studying DELEGATES and EVENTS and I managed to get it to work.
For those who are in the same situation:
Start here for an explanation on using delegates and events: DELEGATES and EVENTS
Just based on that, you can set up a delegate and create an event when you get a response from AuthenticationRequest().
Once that's set up, create a listener/subscriber in your GameManager class or your singleton and point it to the event.
Once the event is triggered, the listener then starts whatever method you need it to do (i.e assign a value to a variable, perform an operation, etc).
PATRICK: Mate, you have been great and patient and thank you for your time spent on this. It's not easy to get aquainted with a whole new environement but with baby steps and super awesome support, we'll get there!
Many thanks!
Customer Support
said
about 6 years ago
Hey Alex, Happy I could help. You're more than welcome.
Alex Catana
Hello everyone,
I'm starting incorporating GameSparks into my application, but am a bit stuck very close to shore.
Let's say I am retrieving the account details as so:
When I run the script above, Debug 2 is executed first and returns "Player name is: ". Then Debug 3 is executed and the text component shows "Hello, ". Then Debug 1 is executed showing "Player name is: Whatever".
If I then run the script again, all Debugs show the name and the name is displayed on screen.
Why is this?
Even if I put AccountDetailsRequest() and assigning the name to the text compononent in the same method, the behaviour is the same.
This happens with all the GS API calls (be it this or LogEventRequest, or whatever) of course.
How could I both get the information and display the variable on screen with only one call.
I'm sure it is something simple, but I've been looking up and down the forum and internet and can't find an explanation for this.
Understanding this will allow me to apply the same knowledge to all the other API calls.
Hi Alex,
This is due to the asynchronous nature of requests. We can not always predict with certainty the time at which the response is received. This leaves the potential for us to attempt to refernce data that has not yet been acquire. It is for this reason that we use callbacks when utilizing asynchronously acquired data.
Here is an example of funciton I use with callbacks that run when the data I want to use is received:
Here is how I called this function in another class. It's worth noting that I sued lambdas to assign anonymous functions as arguments.
I hope this answers your question. Let me know if you need further clarification on anything.
Best Regards, Patrick.
- Oldest First
- Popular
- Newest First
Sorted by Oldest FirstCustomer Support
Hi Alex,
This is due to the asynchronous nature of requests. We can not always predict with certainty the time at which the response is received. This leaves the potential for us to attempt to refernce data that has not yet been acquire. It is for this reason that we use callbacks when utilizing asynchronously acquired data.
Here is an example of funciton I use with callbacks that run when the data I want to use is received:
Here is how I called this function in another class. It's worth noting that I sued lambdas to assign anonymous functions as arguments.
I hope this answers your question. Let me know if you need further clarification on anything.
Best Regards, Patrick.
Alex Catana
Hello Patrick!
Wow!! Many thanks for your super fast reply.
While I'm sure the example you gave works and is the right way of doing things, it is a bit too advanced for me to follow at this point, I'm afraid. I'm still getting to grips with integrating GameSparks into Unity and the API calls, etc.
I usually learn and understand things by following examples...I take the example, implement it in my test app and see the result and try to make sense of it (99% of the time succesfully). But your example has references to things that are specific to your application and it confuses me a bit :).
Is there any chance that a simplified more generic example can be used? Maybe with how this would be implemented with the AccountDetailsRequest() call (cause this is as generic as it gets)?
It's the flow of things that I ultimately want to get from the example...
many thanks in advance for your time!
Alex
Alex Catana
Hello Patrick! I have replied to your comment about an hour ago...but it hasn't appeared yet. Testing with this to see if it appears
Alex Catana
Trying to reply again.
Many thanks for your prompt reply earlier.
However, because I'm still getting to grips with everything, the example is a bit too advanced for me. I usually learn by testing snippets in my test app, seeing the results and trying to make sense of everything (which works 99% of the time). But your example has bits that are specific to your app which I can't replicate... Lambdas is also something I have yet to learn so that doesn't help either :).
Any chance a more generic example can be used? Something that might use AccountDetailsRequest()? Like just simply requesting the displayName or currency1 amount, storing it in a variable and updating a text component with it (or just printing to console). A simplified example of a callback, so to speak. And once i am up to speed with the more advanced elements in C#/JS, I can expand it myself..
I now understand why what I was trying to do doesn't work, but still looking for a way to work around that.
Many thanks,
Alex
Customer Support
Hey Alex Catana,
Lamdas allow you to invoke logic without defining a function. Essentially it is just inline function declaration.
You will have to use a delegate or lamda to expose the response for any GameSparks Request. Rather than using callbacks you can place a null check within the response and then pass the value to your function as an argument. That may look something like this:
(response) => {
if(response.value != null)
{
MyFunction(response.value);
}
}
Does this make sense?
Best Regards, Patrick.
Customer Support
Hi Alex,
I can understand that.
Hes a working example. In this function, I send a Registration Request. Based on the response it returns, either our Registration was successful, failed, or failed due to the player already existing. In the latter case, we instead perform an Authentication request with the credentials provided.
Does this clear things up for you? Happy to assist further !
Best Regards, Patrick.
Alex Catana
Hi Patrick.
Once again, many thanks for your reply. I actually managed to put the above together by myself from studying the documentation and this bit works as indended! Why I started this topic is...From here I want to retrieve a parameter from the response (i.e. the username or the displayName) and store it in a local variable for other operations.
Assuming the local variable is "myLocalVariable"... I have been trying to assign authResponse.displayName (for example) and then print myLocalVariable to the console. I need this to happen when I call "AuthenticatePlayer(displayName,password);" from another method or from the editor.
But no matter where I put "myLocalVariable=authResponse.displayName" and the "Debug.Log("Name: "+myLocalVariable) it always prints just "Name: ". For example, if i put Debug.Log between lines 35 and 36 in your code, the program seems to run Debug.log first and then assign the value. I have to call it a second time for it to print to console correctly. The way I see it, it executes everything outside the "new RegistrationRequest..." bit (whether is above or below) and then it moves on to actually executing the API call. It doesn't execute in order from top to bottom. Again, I've moved these up and down the method without success.
I hope I am making sense. Your help so far has been great and very much appreciated.
Customer Support
hi Alex,
So a couple of things could be happening here, presuming there are no errors in the response or otherwise.
It may be that you are assigning the variable correctly but that it does not have the appropriate scope for where you are attempting to debug it.
If you look at this example, you can see where I have placed a debug referencing the displayName:
In my test, it succesfully logs my display name to the console.
Hope this helps.
Best Regards, Patrick.
Alex Catana
That is correct Patrick! It does indeed print it to console if you are printing the display name received in the response directly. But this also needs to be assigned to a string variable in the application for other operations.
So the Debug.Log which I'm having problems with is the one that outputs the value of the variable which was passed the authReponse.DisplayName.
So with a button click I want to call "AuthenticationRequest()", assign the "authReponse.DisplayName" to a myVariable string and print Debug.Log("Display name is: "+ myVariable); all in one go. At the moment I have to click the button twice for this to happen. The first time it prints "Display name is: " and the second time it displays correctly.
This leads me to believe that Debug.Log("Display name is: "+ myVariable); is executed first and then the "AuthenticationRequest()". I have tried putting the Debug.Log in various places in the method, but it still gets executed first.
I'm sure it's something simple and stupid...but can't figure it out.
Alex
Alex Catana
UPDATE
I spent all day today studying DELEGATES and EVENTS and I managed to get it to work.
For those who are in the same situation:
Start here for an explanation on using delegates and events: DELEGATES and EVENTS
Just based on that, you can set up a delegate and create an event when you get a response from AuthenticationRequest().
Once that's set up, create a listener/subscriber in your GameManager class or your singleton and point it to the event.
Once the event is triggered, the listener then starts whatever method you need it to do (i.e assign a value to a variable, perform an operation, etc).
PATRICK: Mate, you have been great and patient and thank you for your time spent on this. It's not easy to get aquainted with a whole new environement but with baby steps and super awesome support, we'll get there!
Many thanks!
Customer Support
Hey Alex,
Happy I could help. You're more than welcome.
Best Regards, Patrick.
-
Documentation Notes
-
Design issues with user events
-
Using NoSQL
-
Runtime Collections vs Metadata Collections
-
Anonymous authentication from browser app
-
Modules
-
Movement With Unity
-
Problem with url parameters for downloadables
-
Querying NoSql GameSparks database
-
Challenge accesType
See all 2487 topics