Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Resolved keeping data the same between scenes

Discussion in 'Scripting' started by THELOLMAN69, May 25, 2024.

  1. THELOLMAN69

    THELOLMAN69

    Joined:
    Jan 28, 2023
    Posts:
    12
    I want to be able to keep the data the same between scenes, so like for example, if my health was at 50% and i were to switch scenes, the health would stay 50% instead of resetting back to 100%. If needed, i can post the scripts its just there are a lot that goes into this.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,369
    Some kind of a GameManager construct is usually used for this. Google for more details.

    ULTRA-simple static solution to a GameManager:

    https://forum.unity.com/threads/i-need-to-save-the-score-when-the-scene-resets.1168766/#post-7488068

    https://gist.github.com/kurtdekker/50faa0d78cd978375b2fe465d55b282b

    OR for a more-complex "lives as a MonoBehaviour or ScriptableObject" solution...

    Simple Singleton (UnitySingleton):

    Some super-simple Singleton examples to take and modify:

    Simple Unity3D Singleton (no predefined data):

    https://gist.github.com/kurtdekker/775bb97614047072f7004d6fb9ccce30

    Unity3D Singleton with a Prefab (or a ScriptableObject) used for predefined data:

    https://gist.github.com/kurtdekker/2f07be6f6a844cf82110fc42a774a625

    These are pure-code solutions, DO NOT put anything into any scene, just access it via .Instance

    Alternately you could start one up with a
    RuntimeInitializeOnLoad
    attribute.

    The above solutions can be modified to additively load a scene instead, BUT scenes do not load until end of frame, which means your static factory cannot return the instance that will be in the to-be-loaded scene. This is a minor limitation that is simple to work around.

    If it is a GameManager, when the game is over, make a function in that singleton that Destroys itself so the next time you access it you get a fresh one, something like:

    Code (csharp):
    1. public void DestroyThyself()
    2. {
    3.    Destroy(gameObject);
    4.    Instance = null;    // because destroy doesn't happen until end of frame
    5. }
    There are also lots of Youtube tutorials on the concepts involved in making a suitable GameManager, which obviously depends a lot on what your game might need.

    OR just make a custom ScriptableObject that has the shared fields you want for the duration of many scenes, and drag references to that one ScriptableObject instance into everything that needs it. It scales up to a certain point.
     
    Ryiah likes this.
  3. THELOLMAN69

    THELOLMAN69

    Joined:
    Jan 28, 2023
    Posts:
    12
    Ive tried making a static gamemanager and also making the health and stamina static but nothing worked.

    Here is the scripts i have that go into the health and stamina system


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5.  
    6. public class PlatformGameManager : MonoBehaviour
    7. {
    8.  
    9.     public static PlatformGameManager gameManager { get; private set; }
    10.  
    11.     //Health
    12.     public static UnitHealth _playerHealth = new UnitHealth(100, 100);
    13.     public static UnitHealth _enemyHealth = new UnitHealth(100, 100);
    14.  
    15.     //Stamina
    16.     public static UnitStamina _playerStamina = new UnitStamina(100f, 100f, 30f, false);
    17.  
    18.     // Start is called before the first frame update
    19.  
    20.     void Awake()
    21.     {
    22.         if(gameManager != null && gameManager != this)
    23.         {
    24.             Destroy(this);
    25.         }
    26.         else
    27.         {
    28.             gameManager = this;
    29.         }
    30.     }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PlayerBehavior : MonoBehaviour
    6. {
    7.     [SerializeField] Healthbar _healthbar;
    8.     [SerializeField] StaminaBar _staminabar;
    9.     PlayerController _playerController;
    10.     PlayerBehavior playerBehavior;
    11.     float _playerOriginalSpeed;
    12.     float _playerSprintSpeed;
    13.  
    14.     // Start is called before the first frame update
    15.  
    16.     void Awake()
    17.     {
    18.         _playerController = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerController>();
    19.     }
    20.     void Start()
    21.     {
    22.         _playerOriginalSpeed = _playerController.speed;
    23.         _playerSprintSpeed = _playerController.speed * 2f;
    24.     }
    25.  
    26.     // Update is called once per frame
    27.     void Update()
    28.     {
    29.  
    30.  
    31.         if (Input.GetKey(KeyCode.LeftShift) && PlatformGameManager._playerStamina.Stamina > 0)
    32.         {
    33.             PlayerUseStamina(60f);
    34.             if (_playerController.speed != _playerSprintSpeed)
    35.             {
    36.                 _playerController.speed = _playerSprintSpeed;
    37.              
    38.             }
    39.             else
    40.             {
    41.                 _playerController.speed = _playerOriginalSpeed;
    42.             }
    43.         }
    44.         /*else
    45.         {
    46.             PlayerRegenStamina();
    47.             if (_playerController.speed != _playerOriginalSpeed)
    48.             {
    49.                 _playerController.speed = _playerOriginalSpeed;
    50.             }
    51.         }*/
    52.     }
    53.  
    54.     public void PlayerTakeDmg(int dmg)
    55.     {
    56.         PlatformGameManager._playerHealth.DmgUnit(dmg);
    57.         _healthbar.SetHealth(PlatformGameManager._playerHealth.Health);
    58.     }
    59.  
    60.     public void PlayerHeal(int healing)
    61.     {
    62.         PlatformGameManager._playerHealth.HealUnit(healing);
    63.         _healthbar.SetHealth(PlatformGameManager._playerHealth.Health);
    64.     }
    65.  
    66.     public void PlayerUseStamina(float staminaAmount)
    67.     {
    68.         PlatformGameManager._playerStamina.UseStamina(staminaAmount);
    69.         _staminabar.SetStamina(PlatformGameManager._playerStamina.Stamina);
    70.     }
    71.  
    72.     public void PlayerRegenStamina(float staminaAmount)
    73.     {
    74.         PlatformGameManager._playerStamina.RegenStamina(staminaAmount);
    75.         _staminabar.SetStamina(PlatformGameManager._playerStamina.Stamina);
    76.     }
    77.  
    78.     void OnCollisionEnter2D(Collision2D collision)
    79.     {
    80.         if(collision.gameObject.name == "Enemy")
    81.         {
    82.             PlayerTakeDmg(20);
    83.         }
    84.  
    85.         if(collision.gameObject.tag == "Enemy")
    86.         {
    87.             PlayerTakeDmg(20);
    88.         }
    89.     }
    90. }
    91.  
    Code (CSharp):
    1. public class UnitHealth
    2. {
    3.     // Fields
    4.     public int _currentHealth;
    5.     int _currentMaxHealth;
    6.  
    7.     // Properties
    8.     public int Health
    9.     {
    10.         get
    11.         {
    12.             return _currentHealth;
    13.         }
    14.         set
    15.         {
    16.             _currentHealth = value;
    17.         }
    18.      
    19.     }
    20.  
    21.     public int MaxHealth
    22.     {
    23.         get
    24.         {
    25.             return _currentMaxHealth;
    26.         }
    27.         set
    28.         {
    29.             _currentMaxHealth = value;
    30.         }
    31.      
    32.     }
    33.  
    34.     // Constructor
    35.     public UnitHealth(int health, int maxHealth)
    36.     {
    37.         _currentHealth = health;
    38.         _currentMaxHealth = maxHealth;
    39.     }
    40.  
    41.     // Methods
    42.     public void DmgUnit(int dmgAmount)
    43.     {
    44.         if (_currentHealth > 0)
    45.         {
    46.             _currentHealth -= dmgAmount;
    47.         }
    48.     }
    49.  
    50.     public void HealUnit(int healAmount)
    51.     {
    52.         if (_currentHealth < _currentMaxHealth)
    53.         {
    54.             _currentHealth -= healAmount;
    55.         }
    56.         if (_currentHealth > _currentMaxHealth)
    57.         {
    58.             _currentHealth = _currentMaxHealth;
    59.         }
    60.     }
    61. }
    62.  
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5.  
    6. public class Healthbar : MonoBehaviour
    7. {
    8.     [SerializeField] Slider _healthSlider;
    9.  
    10.     private void Start()
    11.     {
    12.         _healthSlider = GetComponent<Slider>();
    13.     }
    14.     public void SetMaxHealth(int maxHealth)
    15.     {
    16.         _healthSlider.maxValue = maxHealth;
    17.         _healthSlider.value = maxHealth;
    18.     }
    19.    
    20.     public void SetHealth(int health)
    21.     {
    22.         _healthSlider.value = health;
    23.     }
    24. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5.  
    6. public class StaminaBar : MonoBehaviour
    7. {
    8.     [SerializeField] Slider _staminaSlider;
    9.  
    10.     private void Start()
    11.     {
    12.         _staminaSlider = GetComponent<Slider>();
    13.     }
    14.     public void SetMaxStamina(float maxStamina)
    15.     {
    16.         _staminaSlider.maxValue = maxStamina;
    17.         _staminaSlider.value = maxStamina;
    18.     }
    19.    
    20.     public void SetStamina(float stamina)
    21.     {
    22.         _staminaSlider.value = stamina;
    23.     }
    24. }
     
  4. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,687
    You're missing the most important part that is in @Kurt-Dekker's singletons:
    DontDestroyOnLoad
    . If you don't assign this to a script it will be destroyed when you switch scenes.
     
    spiney199 likes this.
  5. THELOLMAN69

    THELOLMAN69

    Joined:
    Jan 28, 2023
    Posts:
    12
    ive created the singleton script, how would i go about assigning
    DontDestroyOnLoad
    to a script, ive been trying to assign it to my _playerHealth and _playerStamina but it wont let me, is there a specific way to do it.
     
  6. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,687
    spiney199 likes this.
  7. THELOLMAN69

    THELOLMAN69

    Joined:
    Jan 28, 2023
    Posts:
    12
    How would i access the SingletonSimple.Instance from other scripts. I got the script all set up i just need other scripts to access it so they wont get erased.
     
  8. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    8,396
    It's a static property, so just access it via
    [SingletonClassName].Instance
    .

    This is starting to feel less like a singleton question and more of a 'how do I code' question now.
     
    Spy-Master likes this.
  9. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,369
    All of these things:

    just mean it is time for you to start debugging your code.

    By debugging you can find out exactly what your program is doing so you can fix it.

    https://docs.unity3d.com/Manual/ManagedCodeDebugging.html

    Use the above techniques to get the information you need in order to reason about what the problem is.

    You can also use
    Debug.Log(...);
    statements to find out if any of your code is even running. Don't assume it is.

    Once you understand what the problem is, you may begin to reason about a solution to the problem.


    Remember, move slowly, move carefully, one tiny piece of success at a time. You posted a gaggle of five (5) separate scripts up there with no further comment which leads us all to believe you're not making the effort to understand what coding is and how to do it.

    That's why Spiney writes:


    Try this pattern:

    Imphenzia: How Did I Learn To Make Games:

     
  10. THELOLMAN69

    THELOLMAN69

    Joined:
    Jan 28, 2023
    Posts:
    12
    Sorry, ive never really dealt with singletons before and im just struggling to fit them into my code, ill try both of your suggestions and see what works.