question

hapygames avatar image
hapygames asked

Is there a way to check if a Player already has Statistics or not?

To be more precise:

I have the LoginWithAndroidDevice method, which logs the Player in, without the need of an Email or Password, and I wondered if there is a way to check on the Resultcallback, if the Player already has any Statistics created.

If the Player does not have any yet, statistics should be created for him, but if he does, it should be ignored and the Player should be logged in, without the creation or modifying of his/her Statistics.

I tried using the code which Updates the Player Statistics, without giving a Value, but this resets the Stats to 0, every time the Player logs in with the LoginWithAndroidDevice.


public void UpdatePlayerStats()
    {
        PlayFabClientAPI.UpdatePlayerStatistics(new UpdatePlayerStatisticsRequest
        {
            // request.Statistics is a list, so multiple StatisticUpdate objects can be defined if required.
            Statistics = new List<StatisticUpdate>
            {
                new StatisticUpdate { StatisticName = "PlayerLevel", Value = 1},
                new StatisticUpdate { StatisticName = "AttackDamage", Value = 1},
                new StatisticUpdate { StatisticName = "PlayerHealth", Value = 1},
                new StatisticUpdate { StatisticName = "SpeedLevel", Value = 1},
            }
        },
        result =>
        {
            Debug.Log("User statistics updated");
        },
        error =>
        {
            Debug.LogError(error.GenerateErrorReport());
        });;
    }

Is there a way to ask if the StatisticName already exists, and if yes, just skip the new StatisticUpdate?

I imagine it to look something like this in the end (I know that it´s wrong in this example):

public void UpdatePlayerStats()
    {
        PlayFabClientAPI.UpdatePlayerStatistics(new UpdatePlayerStatisticsRequest
        {
            // request.Statistics is a list, so multiple StatisticUpdate objects can be defined if required.



	  if(Statistics already exist)

	  {
	
		//Do nothing and just login

	  }

	  else

	  {
	        Statistics = new List<StatisticUpdate>
                {
                    new StatisticUpdate { StatisticName = "PlayerLevel", Value = 1},
                    new StatisticUpdate { StatisticName = "AttackDamage", Value = 1},
                    new StatisticUpdate { StatisticName = "PlayerHealth", Value = 1},
                    new StatisticUpdate { StatisticName = "SpeedLevel", Value = 1},
                }
	  }
            
        },
        result =>
        {
            Debug.Log("User statistics updated");
        },
        error =>
        {
            Debug.LogError(error.GenerateErrorReport());
        });;
    }
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Sarah Zhang avatar image
Sarah Zhang answered

You can call the Client API - GetPlayerStatistics to get the player’s statistics list to determine whether you have already updated their statistics. To update the statistics according to the result of GetPlayerStatistics, the sample code could be something like this.

using PlayFab;
using PlayFab.ClientModels;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class UpdateStatistics : MonoBehaviour
{
    public List<string> StatisticNames = new List<string> { "PlayerLevel", "AttackDamage", "PlayerHealth", "SpeedLevel" };

    void Start()
    {
        UpdatePlayerStats();
    }

    public void UpdatePlayerStats()
    {
        PlayFabClientAPI.LoginWithAndroidDeviceID(new LoginWithAndroidDeviceIDRequest()
        {
            AndroidDeviceId = "[YourDeviceId]",
            CreateAccount = true,
            TitleId = "[YourTitleId]"
        }, OnSuccess, OnFailure);

    }

    private void OnSuccess(LoginResult result)
    {
        PlayFabClientAPI.GetPlayerStatistics(new GetPlayerStatisticsRequest() { StatisticNames = StatisticNames }, OnGetStatisticsSuccess, OnFailure);
    }

    private void OnGetStatisticsSuccess(GetPlayerStatisticsResult result)
    {
        Debug.Log(result.Statistics.Count);
        if (result.Statistics == null || result.Statistics.Count ==0)
        {
            Debug.Log("There are no specific statistics.");
            //Update the initial statistics.
            PlayFabClientAPI.UpdatePlayerStatistics(new UpdatePlayerStatisticsRequest
            {
                // request.Statistics is a list, so multiple StatisticUpdate objects can be defined if required.
                Statistics = new List<StatisticUpdate>
            {
                new StatisticUpdate { StatisticName = "PlayerLevel", Value = 1},
                new StatisticUpdate { StatisticName = "AttackDamage", Value = 1},
                new StatisticUpdate { StatisticName = "PlayerHealth", Value = 1},
                new StatisticUpdate { StatisticName = "SpeedLevel", Value = 1},
            }
            }, OnUpdateStatisticsSuccess, OnFailure);
        }
        else
        {
            var statisitcnamesList = new List<string>();
            foreach (var item in result.Statistics)
            {
                Debug.Log("This statistic exists - " + item.StatisticName);
                statisitcnamesList.Add(item.StatisticName);
            }
            var expectedList = StatisticNames.Except(statisitcnamesList);
            if (expectedList.Count() == 0)
            {
                Debug.Log("All statistic exist");
            }
            else
            { 
                foreach (var item in expectedList)
                {
                    Debug.Log("This statistic needs to be updated - " + item.ToString());
                }
                //Update the initial statistics according to the expectedList.
            }

        }
    }

    private void OnUpdateStatisticsSuccess(UpdatePlayerStatisticsResult obj)
    {
        Debug.Log("User statistics updated");
    }

    private void OnFailure(PlayFabError error)
    {
        Debug.Log(error.GenerateErrorReport());
    }

}

Besides, if you only would like to add initial player statistics for the players whose newly registered to the title. You can also consider setting up a PlayFab Rule to use the event - player_added_title to trigger the actions - increments player statistic. Updating the statistics on the backend also would be safer than updating them on clients. You can check the documentation - Actions & Rules quickstart - PlayFab | Microsoft Docs for more information about how to use PlayFab Rules.

1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

hapygames avatar image hapygames commented ·

Hello, I want to thank you for your help.

Thank you so much! I wish the whole PlayFab-Team all good and I hope that you guys keep up the wonderful work!

Have a nice day!

0 Likes 0 ·
hapygames avatar image
hapygames answered

Good day,

I found an issue that I can not fix.

When I am trying to update the Statistics of the LoginWithAndroidDeviceID Player, after changing the Stats to any different value, I do not get any error, but when rejoining the game, the Stats are the same as before, they didn´t update.

For example I have all my Statistics to 1 at first.

Then I change their value to 2, and reconnect with LoginWithAndroidDeviceID (Basically, I just restart the whole game: close it, re-open it and connect again with LoginWithAndroidDeviceID).


The Stats are being set back to 1, when rejoining the game.

(Everything works fine though, when logging in, using the LoginWithEmailAddressRequest).

I use this code to Update the Stats:

    public void UpdatePlayerStats()
    {
        PlayFabClientAPI.UpdatePlayerStatistics(new UpdatePlayerStatisticsRequest
        {
            // request.Statistics is a list, so multiple StatisticUpdate objects can be defined if required.
            Statistics = new List<StatisticUpdate> 
            {
                new StatisticUpdate { StatisticName = "PlayerLevel", Value = playerLevel },
                new StatisticUpdate { StatisticName = "AttackDamage", Value = attackDamage },
                new StatisticUpdate { StatisticName = "PlayerHealth", Value = playerHealth },
                new StatisticUpdate { StatisticName = "SpeedLevel", Value = speedLevel },
            }
        },
        result => 
        { 
            Debug.Log("User statistics updated");
        },
        error => 
        { 
            Debug.LogError(error.GenerateErrorReport()); 
        });
    }

If this part of the code, alone, doesn´t help to find the issue, here are the 2 Scripts that I use:

Script 1:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using PlayFab;
using PlayFab.ClientModels;
using System;
using TMPro;
using System.Linq;


public class PlayerStatsManager : MonoBehaviour
{
    private GetPlayerStatisticsRequest requestStats; 


    public int playerLevel;
    public int attackDamage;
    public int playerHealth;
    public int speedLevel;


    private TMP_Text playerLevelText;
    private TMP_Text attackDamageText;
    private TMP_Text playerHealthText;
    private TMP_Text speedLevelText;


    private Button attackDamageUpgradeButton;
    private Button playerHealthUpgradeButton;
    private Button speedLevelUpgradeButton;




    private void Awake()
    {
        GetStatistics();
    }


    public void UpdatePlayerStats()
    {
        PlayFabClientAPI.UpdatePlayerStatistics(new UpdatePlayerStatisticsRequest
        {
            // request.Statistics is a list, so multiple StatisticUpdate objects can be defined if required.
            Statistics = new List<StatisticUpdate> 
            {
                new StatisticUpdate { StatisticName = "PlayerLevel", Value = playerLevel },
                new StatisticUpdate { StatisticName = "AttackDamage", Value = attackDamage },
                new StatisticUpdate { StatisticName = "PlayerHealth", Value = playerHealth },
                new StatisticUpdate { StatisticName = "SpeedLevel", Value = speedLevel },
            }
        },
        result => 
        { 
            Debug.Log("User statistics updated");
        },
        error => 
        { 
            Debug.LogError(error.GenerateErrorReport()); 
        });
    }


    public void GetStatistics()
    {
        PlayFabClientAPI.GetPlayerStatistics(new GetPlayerStatisticsRequest(), result => {


            PlayFabClientAPI.GetPlayerCombinedInfo(new GetPlayerCombinedInfoRequest
            {
                InfoRequestParameters = new GetPlayerCombinedInfoRequestParams
                {
                    GetPlayerStatistics = true
                }
            }, equals =>
            {
                //Show the Statistics to the Player
                StartCoroutine(GetNeededComponents());


            }, failure => {
                //CustomAccountManagement.customAccountManagement.OnPlayFabError(error);
                Debug.LogError(failure.GenerateErrorReport());
            });


            OnGetStatistics(result);


        }, error =>
        {
            Debug.LogError(error.GenerateErrorReport());
        });
    }


    private void OnGetStatistics(GetPlayerStatisticsResult result)
    {
        //Debug.Log(result.Statistics.Count);
        if (result.Statistics == null || result.Statistics.Count == 0)
        {
            //Debug.Log("There are no specific statistics.");
            //Update the initial statistics.
            PlayFabClientAPI.UpdatePlayerStatistics(new UpdatePlayerStatisticsRequest
            {
                // request.Statistics is a list, so multiple StatisticUpdate objects can be defined if required.
                Statistics = new List<StatisticUpdate>
                {
                new StatisticUpdate { StatisticName = "PlayerLevel", Value = 1},
                new StatisticUpdate { StatisticName = "AttackDamage", Value = 1},
                new StatisticUpdate { StatisticName = "PlayerHealth", Value = 1},
                new StatisticUpdate { StatisticName = "SpeedLevel", Value = 1},
                }
            },
            equals =>
            {
                Debug.Log("User statistics created");


                Debug.Log("Received the following Statistics:");
                foreach (var eachStat in result.Statistics)
                {
                    Debug.Log("Statistic (" + eachStat.StatisticName + "): " + eachStat.Value);


                    switch (eachStat.StatisticName)
                    {
                        case "PlayerLevel":
                            playerLevel = eachStat.Value;
                            break;
                        case "AttackDamage":
                            attackDamage = eachStat.Value;
                            break;
                        case "PlayerHealth":
                            playerHealth = eachStat.Value;
                            break;
                        case "SpeedLevel":
                            speedLevel = eachStat.Value;
                            break;
                        default:
                            break;
                    }
                }


                DisplayStats();
            },
            error =>
            {
                Debug.LogError(error.GenerateErrorReport());
            });
        }
        else
        {
            Debug.Log("Received the following Statistics:");
            foreach (var eachStat in result.Statistics)
            {
                Debug.Log("Statistic (" + eachStat.StatisticName + "): " + eachStat.Value);


                switch (eachStat.StatisticName)
                {
                    case "PlayerLevel":
                        playerLevel = eachStat.Value;
                        break;
                    case "AttackDamage":
                        attackDamage = eachStat.Value;
                        break;
                    case "PlayerHealth":
                        playerHealth = eachStat.Value;
                        break;
                    case "SpeedLevel":
                        speedLevel = eachStat.Value;
                        break;
                    default:
                        break;
                }
            }
        }
    }


    /*public void CheckStats()
    {
        PlayFabClientAPI.GetPlayerStatistics(requestStats, result =>
        {
            foreach (var eachStat in result.Statistics)
            {
                switch (eachStat.StatisticName)
                {
                    case "PlayerLevel":
                        playerLevel = eachStat.Value;
                        break;
                    case "AttackDamage":
                        if (attackDamage >= 100)
                        {
                            attackDamage = 100;
                            attackDamageUpgradeButton.gameObject.SetActive(false);
                        }
                        else if (attackDamage <= 0)
                        {
                            attackDamage = 0;
                        }
                        break;
                    case "PlayerHealth":
                        if (playerHealth >= 100)
                        {
                            playerHealth = 100;
                            playerHealthUpgradeButton.gameObject.SetActive(false);
                        }
                        else if (playerHealth <= 0)
                        {
                            playerHealth = 0;
                        }
                        break;
                    case "SpeedLevel":
                        if (speedLevel >= 100)
                        {
                            speedLevel = 100;
                            speedLevelUpgradeButton.gameObject.SetActive(false);
                        }
                        else if (speedLevel <= 0)
                        {
                            speedLevel = 0;
                        }
                        break;
                    default:
                        break;
                }
            }
        }, error => {
            Debug.LogError(error.GenerateErrorReport());
        });   
    }*/


    public void DisplayStats()
    {
        attackDamageText.text = attackDamage.ToString();
        playerHealthText.text = playerHealth.ToString();
        speedLevelText.text = speedLevel.ToString();
    }


    private IEnumerator GetNeededComponents()
    {
        yield return new WaitForFixedUpdate();
        {
            attackDamageText = GameObject.Find("SafeArea").transform.Find("MainSettingsPanel").transform.Find("SettingsPanels").transform.Find("PlayerSettingsPanel").transform.Find("AttackDamagePanel").transform.Find("AttackValue").GetComponent<TextMeshProUGUI>();


            attackDamageUpgradeButton = GameObject.Find("SafeArea").transform.Find("MainSettingsPanel").transform.Find("SettingsPanels").transform.Find("PlayerSettingsPanel").transform.Find("AttackDamagePanel").transform.Find("UpgradeButtonDamage").GetComponent<Button>();


            playerHealthText = GameObject.Find("SafeArea").transform.Find("MainSettingsPanel").transform.Find("SettingsPanels").transform.Find("PlayerSettingsPanel").transform.Find("PlayerHealthPanel").transform.Find("HealthValue").GetComponent<TextMeshProUGUI>();


            playerHealthUpgradeButton = GameObject.Find("SafeArea").transform.Find("MainSettingsPanel").transform.Find("SettingsPanels").transform.Find("PlayerSettingsPanel").transform.Find("PlayerHealthPanel").transform.Find("UpgradeButtonHealth").GetComponent<Button>();


            speedLevelText = GameObject.Find("SafeArea").transform.Find("MainSettingsPanel").transform.Find("SettingsPanels").transform.Find("PlayerSettingsPanel").transform.Find("SpeedLevelPanel").transform.Find("SpeedValue").GetComponent<TextMeshProUGUI>();


            speedLevelUpgradeButton = GameObject.Find("SafeArea").transform.Find("MainSettingsPanel").transform.Find("SettingsPanels").transform.Find("PlayerSettingsPanel").transform.Find("SpeedLevelPanel").transform.Find("UpgradeButtonSpeed").GetComponent<Button>();
        }
        //CheckStats();
        DisplayStats();
        StopCoroutine(GetNeededComponents());
    }
}



Script 2:

using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class UpgradeStats : MonoBehaviour
{
    public static UpgradeStats US;


    private PlayerStatsManager psm;
    private GameObject meshPlayer;
    private PhotonView PV;


    private void Awake()
    {
        US = this;
    }


    private void Start()
    {
        FindThePSM();
    }


    private void FindThePSM()
    {
        PV = GameObject.FindGameObjectWithTag("MeshPlayer").GetComponent<PhotonView>();
        if (PV.IsMine)
        {
            psm = PV.gameObject.GetComponent<PlayerStatsManager>();
        }
    }


    public void UpgradeAttackDamage()
    {
        psm.attackDamage = psm.attackDamage + 1;
        //psm.CheckStats();
        psm.UpdatePlayerStats();
        psm.DisplayStats();
    }


    public void UpgradeHealth()
    {


        psm.playerHealth = psm.playerHealth + 1;
        //psm.CheckStats();
        psm.UpdatePlayerStats();
        psm.DisplayStats();
    }


    public void UpgradeSpeedLevel()
    {
        psm.speedLevel = psm.speedLevel + 1;
        //psm.CheckStats();
        psm.UpdatePlayerStats();
        psm.DisplayStats();
    }


    public void UpdateStats()
    {
        psm.UpdatePlayerStats();
    }
}


10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

hapygames avatar image
hapygames answered

Never mind, I fixed the issue!

For the ones who want to know how:

I used Unity´s PlayerPrefs, to automatically fill in the login information (Email and Password), so the Player doesn´t have to do so anymore, when wanting to login another time.

Now here comes the issue:

I put the code that automatically filled in the Information, in the Start function, which caused that every time the Game started, the Start function was automatically called, which fills in the login information.

I got the right Player Stats but it was like the "UpdateStats" function didn´t belong to me.

Everything I had to do was check in which Scene I am, and activate the automatical fill in of the login Information only in the actual Login Scene, that logs in the Player with an Email and a Password.

Here is how the script looks like now.

Before fixing the issue:


public void Start()
    {
        if (string.IsNullOrEmpty(PlayFabSettings.TitleId))
        {
            PlayFabSettings.TitleId = "98F29";
        }


        //Try to AutoLogin the User
        if (PlayerPrefs.HasKey("EMAIL"))
        {
            if (PlayerPrefs.GetString("EMAIL", userEmail) != "" && PlayerPrefs.GetString("PASSWORD", userPassword) != "")
            {
                userEmail = PlayerPrefs.GetString("EMAIL");
                userPassword = PlayerPrefs.GetString("PASSWORD");




                var request = new LoginWithEmailAddressRequest { Email = userEmail, Password = userPassword };
                PlayFabClientAPI.LoginWithEmailAddress(request, OnAutoSetLoginDataResult, OnPlayFabError);
            }
        }
        else
        {
#if UNITY_ANDROID
            var requestAndroid = new LoginWithAndroidDeviceIDRequest { AndroidDeviceId = ReturnMobileID(), CreateAccount = true };
            PlayFabClientAPI.LoginWithAndroidDeviceID(requestAndroid, OnAutoSetMobileLoginDataResult, OnPlayFabError);
#endif


#if UNITY_IOS
            var requestIOS = new LoginWithIOSDeviceIDRequest { DeviceId = ReturnMobileID(), CreateAccount = true};
            PlayFabClientAPI.LoginWithIOSDeviceID(requestIOS, OnAutoSetMobileLoginDataResult, OnPlayFabError);
#endif
        }
    }

After fixing the issue:

    public int currentScene;
    private int loginScene = 1;



    public override void OnEnable()
    {
        base.OnEnable();
        PhotonNetwork.AddCallbackTarget(this);
        SceneManager.sceneLoaded += OnSceneFinishedLoading;
    }


    public override void OnDisable()
    {
        base.OnDisable();
        PhotonNetwork.RemoveCallbackTarget(this);
        SceneManager.sceneLoaded -= OnSceneFinishedLoading;
    }


    void OnSceneFinishedLoading(Scene scene, LoadSceneMode mode)
    {
        currentScene = scene.buildIndex;
        if (currentScene == loginScene)
        {
            AutomaticallyLogin();
        }
    }




    public void AutomaticallyLogin()
    {
        if (string.IsNullOrEmpty(PlayFabSettings.TitleId))
        {
            PlayFabSettings.TitleId = "98F29";
        }


        //Try to AutoLogin the User
        if (PlayerPrefs.HasKey("EMAIL"))
        {
            if (PlayerPrefs.GetString("EMAIL", userEmail) != "" && PlayerPrefs.GetString("PASSWORD", userPassword) != "")
            {
                userEmail = PlayerPrefs.GetString("EMAIL");
                userPassword = PlayerPrefs.GetString("PASSWORD");




                var request = new LoginWithEmailAddressRequest { Email = userEmail, Password = userPassword };
                PlayFabClientAPI.LoginWithEmailAddress(request, OnAutoSetLoginDataResult, OnPlayFabError);
            }
        }
        else
        {
#if UNITY_ANDROID
            var requestAndroid = new LoginWithAndroidDeviceIDRequest { AndroidDeviceId = ReturnMobileID(), CreateAccount = true };
            PlayFabClientAPI.LoginWithAndroidDeviceID(requestAndroid, OnAutoSetMobileLoginDataResult, OnPlayFabError);
#endif


#if UNITY_IOS
            var requestIOS = new LoginWithIOSDeviceIDRequest { DeviceId = ReturnMobileID(), CreateAccount = true};
            PlayFabClientAPI.LoginWithIOSDeviceID(requestIOS, OnAutoSetMobileLoginDataResult, OnPlayFabError);
#endif
        }
    }

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.