So I create my health bar as a scriptable object with the following code:
(The health decreases automatically with time)
[CreateAssetMenu]
public class PlayerHealth : ScriptableObject
{
public float health;
public float deathRate;
/*private void Update()
{
health = health - (deathRate * Time.deltaTime);
}
*/
}
I then created the health scriptable object in my asset files, and set it to 100
![alt text][1]
And then I created UI slider to display my health on screen and created a script to manage UI:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class HealthUI : MonoBehaviour
{
public PlayerHealth player;
public Slider HealthBar;
// Start is called before the first frame update
public PlayerHunger hunger;
public Slider HungerBar;
public void Start()
{
player.health = 100f;
}
public void Update()
{
//HealthBar.value = HealthBar.maxValue;
player.health = player.health - (player.deathRate * Time.deltaTime);
HealthBar.value = player.health;
}
}
When I exit game mode the slider goes back to full bar like it should however the health value in scriptable object did not-- in this case it stucks at 95.
What am I doing wrong here? Where should the decreasing of health code be placed? In the UI or in the health scriptable object script???
There’s no reason to do that. Scriptable Objects are usually created to store data assets that are shared across multiple objects, and “PlayerHealth” is definitely not something like that.
Health can be implemented as a single number, and there’s not much of a reason to make it more complicated than that.
I would guess that because scriptable object exists as a global object outside of the scene, the changes to it get saved in the editor.
Place health into a component, instead of a scriptable object, that will solve your troubles.
public class Player: MonoBehaviour{
[SerializeField] int health = 100;
}
This is precisely what’s happening and why if you want to use it in this fashion you need to have code somewhere that initializes it to a default value before you try to use it.
This thread should probably be in the Scripting section. But, anyway, it’s fine to use a ScriptableObject asset for global variables, as Ryan Hipple described in Three ways to architect your game with ScriptableObjects - Architect for Variables. This way your player’s health value can persist across scene changes, and all scenes can have a reference to the same health value asset without having to do any runtime lookups. You just need to initialize it on game start as both folks explained above.
@TonyLi precisely this. The reason I want my health value to be a scriptable objects is for it to be consistent across scenes. Thanks for the article! Will read through it
@neginfinity The reason I set health value to a scriptable object is for it to stay the same between scene transitions. I tried attaching it to the player as mono behavior object but I just couldn’t get it to move with the player between scenes…
Just use DontDestroyOnLoad and make sure to properly serialize your ScriptableObjects. Really though you shouldn’t be using it for this unless multiple things need to access and adjust player health for whatever reason.
Unity says a lot of things and often they’re far from best practice. Player health is not something that really requires or even benefits from this specific level of loose coupling.
Scriptables allow for extremely easy loose coupling that actually works with game development so there aren’t 11 months between game updates, Anders.
My dude, the moment you find out that dictionaries have more than one definition for a word and that loose coupling as a term encompasses a lot of practices that exist outside of enterprise software, the less insufferable every like half of your posts will be.
It is absolutely loose coupling and allows for the easy swapping in an out of any potential breakages which is why it is ideal for the kind of rapid iteration that occurs in gamedev.
This way of doing things can be powerful, but you know, shouldn’t be “PlayerHealth”, it should be Health and not be specialized. Then it could be modular. And then you could create all sorts of health objects for all sort of reasons and you could switch between those back an forth on all of your creatures/objects need health.
Write once, use bazillion times. (And no, literarily write once, then just right click… create… rename… drag and drop… profit)
Just a note that I am pretty sure the variable isn’t truly saved in the way you think. At least it use to be the case that between entering/exiting Play mode it would be saved, but if you do something like close your project and reopen it, it will reset (I think an assembly reload resets it too).
But maybe things have changed with Scriptable Objects in recent years.