Forum begins after the advertisement:

 


[Part 17] Current stats on the pause screen do not refresh

Home Forums Video Game Tutorial Series Creating a Rogue-like Shoot-em Up in Unity [Part 17] Current stats on the pause screen do not refresh

Viewing 5 posts - 1 through 5 (of 5 total)
  • Author
    Posts
  • #18014
    Eray
    Level 7
    Bronze Supporter (Patron)
    Helpful?
    Up
    0
    ::

    When a player adds a passive item to their inventory or upgrades one, the current stats on the pause screen do not refresh. However, when a player picks up a health or speed potion, the according stats do refresh. How can I fix this

    edit: The current health stat is refreshed properly the problem is with the other stats.

    my playerstats.cs

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Runtime.InteropServices.WindowsRuntime;
    using TMPro;
    using Unity.VisualScripting;
    using UnityEngine;
    using UnityEngine.SceneManagement;
    using UnityEngine.UI;
    
    public class PlayerStats : MonoBehaviour
    {
        CharacterData characterData;
        public CharacterData.Stats baseStats;
        PlayerInventory inventory;
        PlayerAnimator playerAnimator;
        [HideInInspector] public int weaponIndex;
        [HideInInspector] public int passiveItemIndex;
    
        [SerializeField] CharacterData.Stats actualStats;
    
        float health;
    
        #region Current Stats
        public float CurrentHealth
        {
            get { return health; }
            set
            {
                // currentHealth değişkeni her değiştirildiğinde set bloğu çalışır ve eğer atanmaya çalışılan "value", mevcut değerden farklı ise atama işlemi yapılır
                if (health != value)
                {
                    health = value;
                    if (GameManager.instance != null)
                    {
                        GameManager.instance.currentHealthDisplay.text = string.Format(
                            "Health: {0} / {1}",
                            health, actualStats.maxHealth
                        );
                    }
                }
            }
        }
    
        public float MaxHealth
        {
            get { return actualStats.maxHealth; }
    
            // If we try and set the max health, the UI interface
            // on the pause screen will also be updated.
            set
            {
                //Check if the value has changed
                if (actualStats.maxHealth != value)
                {
                    actualStats.maxHealth = value;
                    if (GameManager.instance != null)
                    {
                        GameManager.instance.currentHealthDisplay.text = string.Format(
                            "Health: {0} / {1}",
                            health, actualStats.maxHealth
                        );
                    }
                    //Update the real time value of the stat
                    //Add any additional logic here that needs to be executed when the value changes
                }
            }
        }
    
        public float CurrentRecovery
        {
            get { return Recovery; }
            set { Recovery = value; }
        }
    
        public float Recovery
        {
            get { return actualStats.recovery; }
            set
            {
                //Check if the value has changed
                if (actualStats.recovery != value)
                {
                    actualStats.recovery = value;
                    if (GameManager.instance != null)
                    {
                        GameManager.instance.currentRecoveryDisplay.text = "Recovery: " + actualStats.recovery;
                    }
                }
            }
        }
    
        public float CurrentMoveSpeed
        {
            get { return MoveSpeed; }
            set { MoveSpeed = value; }
        }
        public float MoveSpeed
        {
            get { return actualStats.moveSpeed; }
            set
            {
                //Check if the value has changed
                if (actualStats.moveSpeed != value)
                {
                    actualStats.moveSpeed = value;
                    if (GameManager.instance != null)
                    {
                        GameManager.instance.currentMoveSpeedDisplay.text = "Move Speed: " + actualStats.moveSpeed;
                    }
                }
            }
        }
    
        public float CurrentMight
        {
            get { return Might; }
            set { Might = value; }
        }
        public float Might
        {
            get { return actualStats.might; }
            set
            {
                //Check if the value has changed
                if (actualStats.might != value)
                {
                    actualStats.might = value;
                    if (GameManager.instance != null)
                    {
                        GameManager.instance.currentMightDisplay.text = "Might: " + actualStats.might;
                    }
                }
            }
        }
    
        public float CurrentProjectileSpeed
        {
            get { return Speed; }
            set { Speed = value; }
        }
        public float Speed
        {
            get { return actualStats.speed; }
            set
            {
                //Check if the value has changed
                if (actualStats.speed != value)
                {
                    actualStats.speed = value;
                    if (GameManager.instance != null)
                    {
                        GameManager.instance.currentProjectileSpeedDisplay.text = "Projectile Speed: " + actualStats.speed;
                    }
                }
            }
        }
    
        public float CurrentMagnet
        {
            get { return Magnet; }
            set { Magnet = value; }
        }
        public float Magnet
        {
            get { return actualStats.magnet; }
            set
            {
                //Check if the value has changed
                if (actualStats.magnet != value)
                {
                    actualStats.magnet = value;
                    if (GameManager.instance != null)
                    {
                        GameManager.instance.currentMagnetDisplay.text = "Magnet: " + actualStats.magnet;
                    }
                }
            }
        }
        #endregion
    
        // Oyuncunun seviyesi ve deneyim puanı
        [HideInInspector] public int experience = 0;
        [HideInInspector] public int level = 1;
        [HideInInspector] public int experienceCap = 100;
        [HideInInspector] public int experienceCapIncrease;
    
        // Oyuncu hasar alma kısıtlamaları
        [HideInInspector] public float invincibilityDuration;
        [HideInInspector] float invincibilityTimer;
        [HideInInspector] bool isInvincible = false;
    
        // Potion timerları
        [HideInInspector] public float oldMoveSpeed;
        [HideInInspector] public bool isSpeedBoosted = false;
        [HideInInspector] public Coroutine activeSpeedBoostCoroutine;
    
    
        // Database
        [HideInInspector] public int playerScore;
        [HideInInspector] public string playerName;
    
        [Header("UI")]
        public Image healthBar;
        public Image expBar;
        public TextMeshProUGUI levelText;
    
        public ParticleSystem damageEffect;
    
    
        void Awake()
        {
            characterData = CharacterSelector.GetData();
            if (CharacterSelector.instance) 
                CharacterSelector.instance.DestroySingleton();
    
            inventory = GetComponent<PlayerInventory>();
    
            baseStats = actualStats = characterData.stats;
            health = actualStats.maxHealth;
    
            playerAnimator = GetComponent<PlayerAnimator>();
            playerAnimator.SetAnimatorController(characterData.animationController); 
        }
    
        void Start()
        {
            inventory.Add(characterData.StartingWeapon);
    
            GameManager.instance.currentHealthDisplay.text = "Health: " + CurrentHealth;
            GameManager.instance.currentRecoveryDisplay.text = "Recovery: " + CurrentRecovery;
            GameManager.instance.currentMoveSpeedDisplay.text = "Move Speed: " + CurrentMoveSpeed;
            GameManager.instance.currentMightDisplay.text = "Might: " + CurrentMight;
            GameManager.instance.currentProjectileSpeedDisplay.text = "Projectile Speed: " + CurrentProjectileSpeed;
            GameManager.instance.currentMagnetDisplay.text = "Magnet: " + CurrentMagnet;
    
            GameManager.instance.AssingChosenCharacterUI(characterData);
    
            UpdateHealthBar();
            UpdateExpBar();
            UpdateLevelText();
        }
    
        void Update()
        {
            if (invincibilityTimer > 0)
            {
                invincibilityTimer -= Time.deltaTime;
            }
            else if (isInvincible)
            {
                isInvincible = false;
            }
    
            Recover();
            ScoreCalculator();
        }
    
        public void RecalculateStats()
        {
            actualStats = baseStats;
            foreach (PlayerInventory.Slot s in inventory.passiveSlots)
            {
                Passive p = s.item as Passive;
                if (p)
                {
                    actualStats += p.GetBoosts();
                }
            }
    
        }
        public void IncreaseExperience(int amount)
        {
            experience += amount;
    
            LevelUpChecker();   
            UpdateExpBar();
        }
    
        void LevelUpChecker()
        {
            if (experience > experienceCap)
            {
                level++;
                experience -= experienceCap;
                experienceCap += experienceCapIncrease;
    
                UpdateLevelText();
                GameManager.instance.StartLevelUp();
            }
        }
    
        void UpdateExpBar()
        {
            expBar.fillAmount = (float) experience / experienceCap;
        }
    
        void UpdateLevelText()
        {
            levelText.text = "LV " + level.ToString();
        }
    
        public void TakeDamage(float damage)
        {
            if (!isInvincible)
            {
                CurrentHealth -= damage;
                if (damageEffect) Destroy(Instantiate(damageEffect, transform.position, Quaternion.identity), 5f);
    
                invincibilityTimer = invincibilityDuration;
                isInvincible = true;
    
                if (CurrentHealth <= 0)
                {
                    Kill();
                }
                UpdateHealthBar();
            }
        }
    
        void Kill()
        {
    
            if (!GameManager.instance.isGameOver)
            {
                ScoreCalculator(); // ??
                GameManager.instance.AssignLevelReachedUI(level);
                GameManager.instance.AssingChosenWeaponAndPassiveItemsUI(inventory.weaponSlots, inventory.passiveSlots);
                GameManager.instance.GameOver();
    
            }
    
        }
    
        public void RestoreHealth(float amount)
        {
            if (CurrentHealth < actualStats.maxHealth)
            {
                CurrentHealth += amount;
    
                // Make sure the player's health doesn't exceed their maximum health
                if (CurrentHealth > actualStats.maxHealth)
                {
                    CurrentHealth = actualStats.maxHealth;
                }
            }
    
            UpdateHealthBar();
        }
    
        public void UpdateHealthBar()
        {
            healthBar.fillAmount = CurrentHealth / actualStats.maxHealth;
        }
    
        public void ApplySpeedBoost(float speedMultiplier = 2f, float duration = 5f)
        {
            if (!isSpeedBoosted)
            {
                oldMoveSpeed = MoveSpeed;
                MoveSpeed *= speedMultiplier;
                isSpeedBoosted = true;
            }
    
            // Reset timer if one is already running
            if (activeSpeedBoostCoroutine != null)
            {
                StopCoroutine(activeSpeedBoostCoroutine);
            }
    
            activeSpeedBoostCoroutine = StartCoroutine(RemoveSpeedBoostAfterDelay(duration));
    
            if (GameManager.instance != null)
            {
                Debug.LogWarning("SpeedBoost");
                GameManager.GenerateFloatingText("Speed Boost!", transform);
            }
    
        }
    
        private IEnumerator RemoveSpeedBoostAfterDelay(float delay)
        {
            yield return new WaitForSeconds(delay);
    
            MoveSpeed = oldMoveSpeed;
            isSpeedBoosted = false;
            activeSpeedBoostCoroutine = null;
        }
    
    
        public void ScoreCalculator()
        {
            int minionScore = EnemySpawner.minionKillCount * 10;
            int miniBossScore = EnemySpawner.miniBossKillCount * 50;
            int finalBossScore = EnemySpawner.finalBossKillCount * 1000;
    
            playerScore = minionScore + miniBossScore + finalBossScore;
            PlayerStats.PlayerData.score = playerScore;
        }
    
        void Recover()
        {
            if (CurrentHealth < actualStats.maxHealth)
            {
                CurrentHealth += CurrentRecovery * Time.deltaTime;
                CurrentHealth += Recovery * Time.deltaTime;
    
                if (CurrentHealth > actualStats.maxHealth)
                    CurrentHealth = actualStats.maxHealth;
            }
    
            UpdateHealthBar();
        }
    
        [System.Obsolete("Old function that is kept to maintain compatibility with the InventoryManager. Will be removed soon.")]
        public void SpawnWeapon(GameObject weapon)
        {
            // Envanterde boş slot var mı kontrol
            if (weaponIndex >= inventory.weaponSlots.Count)
                Debug.LogError("Inventory slots are already full");
    
            // Başlangıç silahını spawnla
            GameObject spawnedWeapon = Instantiate(weapon, transform.position, Quaternion.identity);
            spawnedWeapon.transform.SetParent(transform);   // Silahı player ın child ı yap 
           // inventory.AddWeapon(weaponIndex, spawnedWeapon.GetComponent<WeaponController>());
            weaponIndex++;
    
        }
    
        [System.Obsolete("No need to spawn passive items directly now.")]
        public void SpawnPassiveItem(GameObject passiveItem)
        {
    
    
    
            // Başlangıç passive itemini spawnla
            GameObject spawnedPassiveItem = Instantiate(passiveItem, transform.position, Quaternion.identity);
            spawnedPassiveItem.transform.SetParent(transform);  
           // inventory.AddPassiveItem(passiveItemIndex, spawnedPassiveItem.GetComponent<PassiveItem>());
            passiveItemIndex++;
    
        }
    
        public static class PlayerData
        {
            public static string Username;
            public static int score;
        }
    
    
    }
    

    my gamemanager.cs

    using System.Collections;
    using System.Collections.Generic;
    using TMPro;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class GameManager : MonoBehaviour
    {
        public static GameManager instance;
    
        // Oyun durumlar�n� tan�mla
        public enum GameState 
        {
            Gameplay,
            Paused,
            GameOver,
            LevelUp
        }
    
        public GameState currentState;
        public GameState previousState;
    
        [Header("Damage Text Settings")]
        public Canvas damageTextCanvas;
        public float textFontSize = 20;
        public TMP_FontAsset textFont;
        public Camera referenceCamera;
    
        [Header("Screens")]
        public GameObject pauseScreen;
        public GameObject resultsScreen;
        public GameObject levelUpScreen;
    
        [Header("Current Stat Displays")]
        public TMP_Text currentHealthDisplay;
        public TMP_Text currentRecoveryDisplay;
        public TMP_Text currentMoveSpeedDisplay;
        public TMP_Text currentMightDisplay;
        public TMP_Text currentProjectileSpeedDisplay;
        public TMP_Text currentMagnetDisplay;
    
        [Header("Result Screen Displays")]
        public Image chosenCharacterImage;
        public TMP_Text chosenCharacterName;
        public TMP_Text levelReachedDisplay;
        public TMP_Text timeSurvivedDisplay;
        public List<Image> chosenWeaponsUI = new List<Image>(3);
        public List<Image> chosenPassiveItemsUI = new List<Image>(3);
    
        [Header("StopWatch")]
        public float timeLimit; // Zaman limiti
        float stopwatchTime;    // Oyunda ge�en s�re
        public TextMeshProUGUI stopwatchDisplay;
    
    
        // Flags
        public bool isGameOver = false; // oyun bitti mi kontrol flag
        public bool choosingUpgrade = false;    // oyuncu seviye atlama ekran�nda m� kontrol
    
        public GameObject playerObject;     // Oyuncunun gameObjectine referans, sendMessage i�in kullan�lacak
    
        void Awake()
        {
            if (instance == null)
            {
                instance = this;
            }
            else
            {
                Debug.LogWarning("EXTRA " + this + " DELETED");
                Destroy(gameObject);
            }
    
    
            DisableScreens();    
        }
        void Update()
        {
            switch (currentState)
            {
                case GameState.Gameplay:
                    CheckForPauseAndResume();
                    UpdateStopWatch();
                    break;
                case GameState.Paused:
                    CheckForPauseAndResume();
                    break;
                case GameState.GameOver:
                    if (!isGameOver)
                    {
                        isGameOver = true;
                        Time.timeScale = 0f;
                        Debug.Log("GAME IS OVER");
                        DisplayResults();
                    }
                    break;
                case GameState.LevelUp:
                    if (!choosingUpgrade)
                    {
                        choosingUpgrade = true;
                        Time.timeScale = 0f;
                        Debug.Log("UPGRADE SCREEN LOADED");
                        levelUpScreen.SetActive(true);
                    }
                    break;
                default:
                    Debug.LogWarning("STATE DOES NOT EXIST");
                    break;
            }
        }
    
        IEnumerator GenerateFloatingTextCoroutine(string text, Transform target, float duration = 1f, float speed = 50f)
        {
            GameObject textObj = new GameObject("Damage Floating Text");
            RectTransform rect = textObj.AddComponent<RectTransform>();
            TextMeshProUGUI tmPro = textObj.AddComponent<TextMeshProUGUI>();
            tmPro.text = text;
            tmPro.horizontalAlignment = HorizontalAlignmentOptions.Center;
            tmPro.verticalAlignment = VerticalAlignmentOptions.Middle;
            tmPro.fontSize = textFontSize;
            if (textFont) tmPro.font = textFont;
            rect.position = referenceCamera.WorldToScreenPoint(target.position);
    
            Destroy(textObj, duration);
    
            // Oluşturulan text objesini canvasın childı yap
            textObj.transform.SetParent(instance.damageTextCanvas.transform);
            textObj.transform.SetSiblingIndex(0);   // text objesini canvasın childları arasında en üste getir. bu "level atlama ekranında text gözükme sorununu çözer
    
            WaitForEndOfFrame w = new WaitForEndOfFrame();
            float t = 0;    // coroutine sayacı
            float yOffset = 0; // hasar text inin konumu
            Vector3 lastKnownPosition = target.position;
            while (t < duration)
            {
                // If the RectTransform is missing for whatever reason, end this loop.
                if (!rect) break;
    
                tmPro.color = new Color(tmPro.color.r, tmPro.color.g, tmPro.color.b, 1 - t / duration);
    
                // Update the enemy's position if it is still around.
                if (target) lastKnownPosition = target.position;
    
                // Pan the text upwards.
                yOffset += speed * Time.deltaTime;
                rect.position = referenceCamera.WorldToScreenPoint(lastKnownPosition + new Vector3(0, yOffset));
    
                yield return w;
                t += Time.deltaTime;
            }
    
        }
        public static void GenerateFloatingText(string text, Transform target, float duration = 1f, float speed = 1f)
        {
            if (!instance.damageTextCanvas)
                return;
    
            if (!instance.referenceCamera)
                instance.referenceCamera = Camera.main;
    
            instance.StartCoroutine(instance.GenerateFloatingTextCoroutine(text, target, duration, speed));
    
        }
    
        public void ChangeState(GameState newState)
        {
            currentState = newState;
        }
    
        public void PauseGame()
        {
            if (currentState != GameState.Paused)
            {
                previousState = currentState;
                ChangeState(GameState.Paused);
                Time.timeScale = 0f;
                pauseScreen.SetActive(true);
                Debug.Log("Game is paused");
            }
        }
    
        public void ResumeGame()
        {
            if (currentState == GameState.Paused)
            {
                /* oyuna devam ederken direkt oyun durumuna de�ilde bir �nceki duruma ge�memizin sebebi, e�er oyuncu oyun harici bir durumda oyunu durduysa
                   o duruma d�nmesini sa�lamak i�in (level atlama durumunda dondurulan oyunun devam ettirildi�inde level atlama ekran�na d�nmesi gibi) */
                ChangeState(previousState);
                Time.timeScale = 1;
                pauseScreen.SetActive(false);
                Debug.Log("Game is resumed");
            }
        }
    
        void CheckForPauseAndResume()
        {
            if (Input.GetKeyDown(KeyCode.Escape))
            {
                if (currentState == GameState.Paused)
                    ResumeGame();
                else
                    PauseGame();
            }
        }
    
        void DisableScreens()
        {
            pauseScreen.SetActive(false);
            resultsScreen.SetActive(false);
            levelUpScreen.SetActive(false);
        }
    
        public void GameOver()
        {
            timeSurvivedDisplay.text = stopwatchDisplay.text;
            ChangeState(GameState.GameOver);
        }
    
        void DisplayResults()
        {
            resultsScreen.SetActive(true);
        }
    
        public void AssingChosenCharacterUI(CharacterData chosenCharacterData)
        {
            chosenCharacterImage.sprite = chosenCharacterData.Icon;
            chosenCharacterName.text = chosenCharacterData.Name;
        }
    
        public void AssignLevelReachedUI(int levelReachedData)
        {
            levelReachedDisplay.text = levelReachedData.ToString();
        }
    
        public void AssingChosenWeaponAndPassiveItemsUI(List<PlayerInventory.Slot> chosenWeaponsData, List<PlayerInventory.Slot> chosenPassiveItemsData)
        {
            if (chosenWeaponsData.Count != chosenPassiveItemsUI.Count || chosenPassiveItemsData.Count != chosenPassiveItemsUI.Count)
            {
                Debug.Log("Chosen weapon and passive items data lists have different lengths");
                return;
            }
    
            // Se�ilmi� silahlar�n ve pasif e�yalar�n verisini sonu� ekran�na ata
            for (int i = 0; i < chosenWeaponsUI.Count; i++)
            {
                // Se�ilmi� silah�n sprite � var m� kontrol
                if (chosenWeaponsData[i].image.sprite)
                {
                    // Se�ilen silah�n UI daki kar��l�k gelen yerini aktif hale getir ve UI daki image � silah�n iconu yap
                    chosenWeaponsUI[i].enabled = true;
                    chosenWeaponsUI[i].sprite = chosenWeaponsData[i].image.sprite;
                }
                else
                {
                    // E�er sprite yoksa UI daki kar��l�k gelen yeri devre d��� b�rak
                    chosenWeaponsUI[i].enabled = false;
                }
            }
    
            for (int i = 0; i < chosenPassiveItemsUI.Count; i++)
            {
                // Se�ilmi� e�yan�n sprite � var m� kontrol
                if (chosenPassiveItemsData[i].image.sprite)
                {
                    // Se�ilen e�yan�n UI daki kar��l�k gelen yerini aktif hale getir ve UI daki image � e�yan�n iconu yap
                    chosenPassiveItemsUI[i].enabled = true;
                    chosenPassiveItemsUI[i].sprite = chosenPassiveItemsData[i].image.sprite;
                }
                else
                {
                    // E�er sprite yoksa UI daki kar��l�k gelen yeri devre d��� b�rak
                    chosenPassiveItemsUI[i].enabled = false;
                }
            }
        }
    
        void UpdateStopWatch()
        {
            stopwatchTime += Time.deltaTime;
    
            UpdateStopWatchDisplay();
    
            if (stopwatchTime > timeLimit)
            {
                playerObject.SendMessage("Kill");   
            }
        }
    
        void UpdateStopWatchDisplay()
        {
            int minutes = Mathf.FloorToInt(stopwatchTime / 60);
            int seconds = Mathf.FloorToInt(stopwatchTime % 60);
    
            stopwatchDisplay.text = string.Format("{0:00}:{1:00}", minutes, seconds);
        }
    
        public void StartLevelUp()
        {
            ChangeState(GameState.LevelUp);
            playerObject.SendMessage("RemoveAndApplyUpgrades");
        }
    
        public void EndLevelUp()
        {
            choosingUpgrade = false;
            Time.timeScale = 1f;
            levelUpScreen.SetActive(false);
            ChangeState(GameState.Gameplay);
        }
    }
    
    #18015
    Alp Apustaja
    Level 7
    AI Assistant
    (BETA)
    Helpful?
    Up
    1
    ::

    In the RecalculateStats() method of the PlayerStats script, you are recalculating the stats, but you are not updating the UI displays. Add the following lines at the end of the RecalculateStats() method:

    public void RecalculateStats()
    {
        actualStats = baseStats;
        foreach (PlayerInventory.Slot s in inventory.passiveSlots)
        {
            Passive p = s.item as Passive;
            if (p)
            {
                actualStats += p.GetBoosts();
            }
        }
    
        // Add these lines to update UI
        Recovery = actualStats.recovery;
        MoveSpeed = actualStats.moveSpeed;
        Might = actualStats.might;
        Speed = actualStats.speed;
        Magnet = actualStats.magnet;
    }

    This will ensure that when passive items are added or upgraded, the UI stats are refreshed just like health and speed potions do.

    has upvoted this post.
    #18021
    Terence
    Level 31
    Keymaster
    Helpful?
    Up
    0
    ::

    Let me know if Alp’s suggestion works. In Part 18, there is a UI revamp for the stats UI, so you can move on to that part to update the UI stat display — the new system is much more robust and requires less coding upkeep / maintenance once it is set up.

    #18023
    Eray
    Level 7
    Bronze Supporter (Patron)
    Helpful?
    Up
    0
    ::

    Alp’s suggestion didn’t work, but the UI revamp in Part 18 solved the issue. Thanks!

    #18024
    Alp Apustaja
    Level 7
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    Great! It seems the UI revamp in Part 18 of the tutorial series resolved the stat refresh issue. The specific details of the solution are not provided in the reference information, so I cannot elaborate on the exact changes made.

    Would you like to share more details about the UI revamp from Part 18 that solved the problem?

Viewing 5 posts - 1 through 5 (of 5 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: