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.
Some kind of a GameManager construct is usually used for this. Google for more details.
ULTRA-simple static solution to a GameManager:
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):
Unity3D Singleton with a Prefab (or a ScriptableObject) used for predefined data:
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:
public void DestroyThyself()
{
Destroy(gameObject);
Instance = null; // because destroy doesn't happen until end of frame
}
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.
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
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlatformGameManager : MonoBehaviour
{
public static PlatformGameManager gameManager { get; private set; }
//Health
public static UnitHealth _playerHealth = new UnitHealth(100, 100);
public static UnitHealth _enemyHealth = new UnitHealth(100, 100);
//Stamina
public static UnitStamina _playerStamina = new UnitStamina(100f, 100f, 30f, false);
// Start is called before the first frame update
void Awake()
{
if(gameManager != null && gameManager != this)
{
Destroy(this);
}
else
{
gameManager = this;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerBehavior : MonoBehaviour
{
[SerializeField] Healthbar _healthbar;
[SerializeField] StaminaBar _staminabar;
PlayerController _playerController;
PlayerBehavior playerBehavior;
float _playerOriginalSpeed;
float _playerSprintSpeed;
// Start is called before the first frame update
void Awake()
{
_playerController = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerController>();
}
void Start()
{
_playerOriginalSpeed = _playerController.speed;
_playerSprintSpeed = _playerController.speed * 2f;
}
// Update is called once per frame
void Update()
{
if (Input.GetKey(KeyCode.LeftShift) && PlatformGameManager._playerStamina.Stamina > 0)
{
PlayerUseStamina(60f);
if (_playerController.speed != _playerSprintSpeed)
{
_playerController.speed = _playerSprintSpeed;
}
else
{
_playerController.speed = _playerOriginalSpeed;
}
}
/*else
{
PlayerRegenStamina();
if (_playerController.speed != _playerOriginalSpeed)
{
_playerController.speed = _playerOriginalSpeed;
}
}*/
}
public void PlayerTakeDmg(int dmg)
{
PlatformGameManager._playerHealth.DmgUnit(dmg);
_healthbar.SetHealth(PlatformGameManager._playerHealth.Health);
}
public void PlayerHeal(int healing)
{
PlatformGameManager._playerHealth.HealUnit(healing);
_healthbar.SetHealth(PlatformGameManager._playerHealth.Health);
}
public void PlayerUseStamina(float staminaAmount)
{
PlatformGameManager._playerStamina.UseStamina(staminaAmount);
_staminabar.SetStamina(PlatformGameManager._playerStamina.Stamina);
}
public void PlayerRegenStamina(float staminaAmount)
{
PlatformGameManager._playerStamina.RegenStamina(staminaAmount);
_staminabar.SetStamina(PlatformGameManager._playerStamina.Stamina);
}
void OnCollisionEnter2D(Collision2D collision)
{
if(collision.gameObject.name == "Enemy")
{
PlayerTakeDmg(20);
}
if(collision.gameObject.tag == "Enemy")
{
PlayerTakeDmg(20);
}
}
}
public class UnitHealth
{
// Fields
public int _currentHealth;
int _currentMaxHealth;
// Properties
public int Health
{
get
{
return _currentHealth;
}
set
{
_currentHealth = value;
}
}
public int MaxHealth
{
get
{
return _currentMaxHealth;
}
set
{
_currentMaxHealth = value;
}
}
// Constructor
public UnitHealth(int health, int maxHealth)
{
_currentHealth = health;
_currentMaxHealth = maxHealth;
}
// Methods
public void DmgUnit(int dmgAmount)
{
if (_currentHealth > 0)
{
_currentHealth -= dmgAmount;
}
}
public void HealUnit(int healAmount)
{
if (_currentHealth < _currentMaxHealth)
{
_currentHealth -= healAmount;
}
if (_currentHealth > _currentMaxHealth)
{
_currentHealth = _currentMaxHealth;
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Healthbar : MonoBehaviour
{
[SerializeField] Slider _healthSlider;
private void Start()
{
_healthSlider = GetComponent<Slider>();
}
public void SetMaxHealth(int maxHealth)
{
_healthSlider.maxValue = maxHealth;
_healthSlider.value = maxHealth;
}
public void SetHealth(int health)
{
_healthSlider.value = health;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class StaminaBar : MonoBehaviour
{
[SerializeField] Slider _staminaSlider;
private void Start()
{
_staminaSlider = GetComponent<Slider>();
}
public void SetMaxStamina(float maxStamina)
{
_staminaSlider.maxValue = maxStamina;
_staminaSlider.value = maxStamina;
}
public void SetStamina(float stamina)
{
_staminaSlider.value = stamina;
}
}
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.
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.
Check his example. Note that his automatically instantiates itself the first time you use it.
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.
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.
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.
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:
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.