Good day,
I have (an issue / a problem) regarding to the Player Statistics.
In this scenario I have 2 Scripts called HealthSystem and CustomAccountManagement.
HealthSystem: This Script manages the Health of the Players
CustomAccountManagement: This Script has all the PlayFab requests.
My (issue / problem) looks in an example like this:
Device 1 (Player 1) recieves his statistic PlayerHealth, after logging in successfully, with a value of 5.
The Script HealthSystem has the float maxHealth which is being set equal to the statistic PlayerHealth, which means the float maxHealth is being set to a value of 5.
Device 2 (Player 2) recieves his statistic PlayerHealth, after logging in successfully, with a value of 2.
The Script HealthSystem has the float maxHealth which is being set equal to the statistic PlayerHealth of the first Device which means the float maxHealth is being also set to a value of 5.
And this shouldn´t happen because the float maxHealth of the second Device should be set to a value of 2.
HealthSystem Script:
using System; using UnityEngine; using Photon.Pun; using TMPro; using System.Collections; using System.Collections.Generic; public class HealthSystem : MonoBehaviourPunCallbacks, IPunObservable { public event EventHandler OnHealthChanged; public HealthBar healthBar; private TMP_Text healthText; public float maxHealth; public float health; int spawnPickerPlayer; int spawnPickerEnemy; private void Start() { if (gameObject.CompareTag("Enemy")) { maxHealth = 1000; health = maxHealth; } if (gameObject.CompareTag("MeshPlayer")) { GetCharacterHealth(); } StartCoroutine(GetNeededComponents()); StartCoroutine(OnPlayerDeath()); } public void GetCharacterHealth() { maxHealth = CustomAccountManagement.CSM.playerHealth; health = maxHealth; //healthText.text = "Health: " + health; //Debug.Log("Invoked GetCharacterHealth"); } public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) { //synchronize Health if (stream.IsWriting) { stream.SendNext(health); } else { health = (float)stream.ReceiveNext(); } } public float GetHealth() { return health; } public float GetHealthPercentage() { return health / maxHealth; } public void Damage(float damageAmount) { health -= damageAmount; if (health < 0) health = 0; if (OnHealthChanged != null) OnHealthChanged(this, EventArgs.Empty); healthBar.SetHealth(); if (gameObject.CompareTag("Enemy")) { healthText.text = "Health: " + (int)health; } } public void Heal(float healAmount) { health += healAmount; if (health > maxHealth) health = maxHealth; if (OnHealthChanged != null) OnHealthChanged(this, EventArgs.Empty); healthBar.SetHealth(); if(gameObject.CompareTag("Enemy")) { healthText.text = "Health: " + (int)health; } } IEnumerator GetNeededComponents() { yield return new WaitForSeconds(0.1f); if (gameObject.CompareTag("Enemy")) { healthText = GetComponentInChildren<TextMeshProUGUI>(); healthText.text = "Health: " + (int)health; } healthBar = GetComponentInChildren<HealthBar>(); healthBar.SetMaxHealth(); StopCoroutine(GetNeededComponents()); yield break; } private void RespawnPlayer() { if(this.CompareTag("MeshPlayer")) { this.gameObject.transform.position = GameSetup.GS.spawnPoints[spawnPickerPlayer].position; } else if(this.gameObject.CompareTag("Enemy")) { this.gameObject.transform.position = GameSetup.GS.wayPoints[spawnPickerEnemy].position; } Heal(maxHealth); if (gameObject.CompareTag("Enemy")) { healthText.text = "Health: " + (int)health; } this.gameObject.SetActive(true); StartCoroutine(OnPlayerDeath()); } IEnumerator OnPlayerDeath() { yield return new WaitUntil(() => GetHealthPercentage() <= 0); { Debug.Log("Player Died"); this.gameObject.SetActive(false); spawnPickerPlayer = UnityEngine.Random.Range(0, GameSetup.GS.spawnPoints.Length); spawnPickerEnemy = UnityEngine.Random.Range(0, GameSetup.GS.wayPoints.Length); Invoke("RespawnPlayer", 2); StopCoroutine(OnPlayerDeath()); } } }
CustomAccountManagement Script (only with the login functions and the Player Statistics request):
Important Detail to know: This Script is a Singleton and doesn´t destroy on load.
using System.Collections; using System.Collections.Generic; using UnityEngine.UI; using UnityEngine; using PlayFab.ClientModels; using PlayFab; using PlayFab.CloudScriptModels; using TMPro; using Photon.Pun; using System; using UnityEngine.SceneManagement; using PlayFab.MultiplayerModels; using System.Linq; public class CustomAccountManagement : MonoBehaviourPunCallbacks { public static CustomAccountManagement CSM; public LoginWithEmailAddressRequest loginWithEmail; public string userEmail; public string userPassword; public string username; public TMP_Text errorMessage; public TMP_Text reasonAndTime; //Virtual Currency public GetPlayerCombinedInfoRequestParams playerInfo; public int currentScene; private int loginScene = 1; [Header("Player Data")] public int HappyCoins; public int playerLevel; public int attackDamage; public int playerHealth; public int speedLevel; #region MobileGuestLogin //Mobile Guest Login private void MobileGuestLogin() { #if UNITY_ANDROID var requestAndroid = new LoginWithAndroidDeviceIDRequest { AndroidDeviceId = ReturnMobileID(), CreateAccount = true }; requestAndroid.InfoRequestParameters = playerInfo; PlayFabClientAPI.LoginWithAndroidDeviceID(requestAndroid, result => { //Request VirtualCurrency, Stats, etc. requestAndroid.InfoRequestParameters = playerInfo; OnLoginResult(result); }, OnPlayFabError); #endif #if UNITY_IOS var requestIOS = new LoginWithIOSDeviceIDRequest { DeviceId = ReturnMobileID(), CreateAccount = true}; PlayFabClientAPI.LoginWithIOSDeviceID(requestIOS, OnLoginMobileResult, OnPlayFabError); #endif } public static string ReturnMobileID() { string deviceID = SystemInfo.deviceUniqueIdentifier; return deviceID; } public void OnClickGuest() { MobileGuestLogin(); } #endregion MobileGuestLogin #region Login //Login private void Login() { loginWithEmail = new LoginWithEmailAddressRequest { Email = userEmail, Password = userPassword }; loginWithEmail.TitleId = PlayFabSettings.TitleId; if (!PlayerPrefs.HasKey("EMAIL") && !PlayerPrefs.HasKey("PASSWORD")) { PlayerPrefs.SetString("EMAIL", userEmail); PlayerPrefs.SetString("PASSWORD", userPassword); } // Request Login to PlayFab API PlayFabClientAPI.LoginWithEmailAddress(loginWithEmail, result => { HappyCoins = result.InfoResultPayload.UserVirtualCurrency["HC"]; //Request VirtualCurrency, Stats, etc. loginWithEmail.InfoRequestParameters = playerInfo; OnLoginResult(result); }, OnPlayFabError); } private void OnLoginResult(LoginResult obj) { Debug.Log("Login was successful!"); GetStatistics(); PhotonNetwork.LoadLevel("Lobby"); } public void OnClickLogin() { PlayerPrefs.SetString("EMAIL", userEmail); PlayerPrefs.SetString("PASSWORD", userPassword); var request = new LoginWithEmailAddressRequest { Email = userEmail, Password = userPassword }; PlayFabClientAPI.LoginWithEmailAddress(request, OnLoginResult, OnPlayFabError); } public void DeleteLoginPlayerPrefs() { PlayerPrefs.DeleteKey("EMAIL"); PlayerPrefs.DeleteKey("PASSWORD"); Debug.Log("Login PlayerPreferences have been deleted."); } #endregion Login #region PlayerStats private GetPlayerStatisticsRequest requestStats; 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 => { }, 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) { UpdatePlayerStats(); } else { 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; } } } } #endregion PlayerStats }