How To Save Health Between Scenes

Hello.

I’m making a 2D videogame in Unity 2020.3.11f1 for a project for my high school. This is the second time I use C# scripting through Visual Studio, and I’m still not acquainted with some terms. The thing is I have an entire script for the main character of my videogame with its movement, attack, knockback… I also have its health programmed in there. The thing is it works perfectly, the health decreases when it has to. But the problem I have is that when the character goes to another scene, the health goes back to its maximum value and I don’t want that, because it looks awkward. The health it’s made through a scriptable object called Float Value. And it’s a heart system, not a health bar system. Since, as I previously said, I’m still not so acquainted with Unity programming and C#, I’m watching tutorials to complete the game, from the series “Make a game like Legend of Zelda using Unity and C#” by Mister Taft Creates, if you want to take a look (more or less, from part 23 to 25). Here’s the codes:

Player Code

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum PlayerState
{
    walk,
    attack,
    interact,
    stagger,
    idle
}

public class PlayerMovement : MonoBehaviour
{
    public PlayerState currentState;
    public float speed;
    private Rigidbody2D myRigidbody;
    private Vector3 change;
    private Animator animator;
    public FloatValue currentHealth;
    public SignalGame playerHealthSignal;


    // Start is called before the first frame update
    void Start()
    {
        currentState = PlayerState.walk;
        animator = GetComponent<Animator>();
        myRigidbody = GetComponent<Rigidbody2D>();
        animator.SetFloat("moveX", 0);
        animator.SetFloat("moveY", -1);
    }

    // Update is called once per frame
    void Update()
    {
        change = Vector3.zero;
        change.x = Input.GetAxisRaw("Horizontal");
        change.y = Input.GetAxisRaw("Vertical");
        if(Input.GetButtonDown("attack") && currentState != PlayerState.attack && currentState != PlayerState.stagger)
        {
            StartCoroutine(AttackCo());
        }
        else if (currentState == PlayerState.walk || currentState == PlayerState.idle)
        {
            UpdateAnimationAndMove();
        }

    }

    private IEnumerator AttackCo() 
    {
        animator.SetBool("attacking", true);
        currentState = PlayerState.attack;
        yield return null;
        animator.SetBool("attacking", false);
        yield return new WaitForSeconds(.3f);
        currentState = PlayerState.walk;
    }

    void UpdateAnimationAndMove() 
    {
        if (change != Vector3.zero)
        {
            MoveCharacter();
            animator.SetFloat("moveX", change.x);
            animator.SetFloat("moveY", change.y);
            animator.SetBool("moving", true);
        }

        else
        {
            animator.SetBool("moving", false);
        }
    }

    void MoveCharacter()
    {
        change.Normalize();
        myRigidbody.MovePosition(
            transform.position + change * speed * Time.fixedDeltaTime
            );
    }

    public void Knock(float knockTime, float damage)
    {
        currentHealth.RuntimeValue -= damage;
        playerHealthSignal.Raise();
        if (currentHealth.RuntimeValue > 0)
        {
            StartCoroutine(KnockCo(knockTime));
        }

        else
        {
            this.gameObject.SetActive(false);

        }
        
    }

    private IEnumerator KnockCo(float knockTime)
    {
        if (myRigidbody != null)
        {
            yield return new WaitForSeconds(knockTime);
            myRigidbody.velocity = Vector2.zero;
            currentState = PlayerState.idle;
            myRigidbody.velocity = Vector2.zero;
        }
    }
}

where Float Value comes from:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu]
public class FloatValue : ScriptableObject, ISerializationCallbackReceiver
{

    public float initialValue;

    [HideInInspector]
    public float RuntimeValue;
    public void OnAfterDeserialize()
    {
        RuntimeValue = initialValue;
    
    }
    public void OnBeforeSerialize(){}

}

If someone knows how to save the health between scenes with these type of scripts I would be really grateful and it would be a lot of help for my project.

Thank you.

What you need is DontDestroyOnLoad. The documentation has an example that should work for you just fine.