Slider that increases and decreases OnTrigger?

What I want is for when the player starts off inside a certain location it’s oxygen bar is full. Then when it exits the location the oxygen bar decreases, and when it returns to that location the oxygen bar increases again. However the problem I’m currently having is that when the player enters or exits, it remembers the value from the last time it was there- instead of increasing or decreasing from it’s current value. What am I doing wrong? Any help would be really appreciated. I’m doing this with 3 scripts:

Oxygen Decreases:

public class Oxygen : MonoBehaviour {

    public float time;
    private Slider oxygenSlider;
    private GameObject oxygen;
    public Slider oxygenAmount;
    public float timeRestore;

    // Use this for initialization

        void Awake()
    {
        float timeRestore = gameObject.GetComponent<Oxygen>().timeRestore;
    }


        void Start () {
        oxygenSlider = oxygen.GetComponent<Slider>();
        oxygenSlider.value = timeRestore;

        oxygenAmount.maxValue = time;
        oxygenAmount.minValue = 0f;
       
    }
   
    // Update is called once per frame
    void Update () {

        time -= timeRestore - Time.deltaTime;
        oxygenAmount.value = time;
       
    }
}

Oxygen Increases:

public class OxygenRestore : MonoBehaviour
{
    public float time;
    private Slider oxygenSlider;
    private GameObject oxygen;
    public Slider oxygenAmount;
    public float timeRestore;

    // Use this for initialization
   
     void Awake()
    {
        float time = gameObject.GetComponent<Oxygen>().time;
    }


     void Start()
    {   oxygenSlider = oxygen.GetComponent<Slider>();
        oxygenSlider.value = time;  

        oxygenAmount.maxValue = 100f;
        oxygenAmount.minValue = timeRestore;    
    }

    // Update is called once per frame
    void Update()
    {
       

        timeRestore += time +  Time.deltaTime;
        oxygenAmount.value = timeRestore;

    }
}

OnTrigger Enter/Stay/Exit

public class InsideShipGravity : MonoBehaviour
{
    public GameObject oxygen;
    public GameObject player;

  

    void OnTriggerEnter2D(Collider2D Collider)
    {
        if (Collider.gameObject.tag == "Player")

        {
            oxygen.GetComponent<Oxygen>().enabled = false;
            oxygen.GetComponent<OxygenRestore>().enabled = true;
        }       
    }

    void OnTriggerStay2D(Collider2D Collider)
    {
        if (Collider.gameObject.tag == "Player")

        {
        if (Collider.gameObject.tag == "Player")

        {
            oxygen.GetComponent<Oxygen>().enabled = false;
            oxygen.GetComponent<OxygenRestore>().enabled = true;
        }       
    }

    void OnTriggerExit2D(Collider2D Collider)
    {
        if (Collider.gameObject.tag == "Player")

        {
        if (Collider.gameObject.tag == "Player")

        {
            oxygen.GetComponent<Oxygen>().enabled = true;
            oxygen.GetComponent<OxygenRestore>().enabled = false;
        }       
    }

I’m also getting the error- NullReferenceException: Object reference not set to an instance of an object.

I would just simplify this to a single class (let’s call it OxygenManager) that has two broad functions:

  1. in the Update() function, slowly consume oxygen at whatever rate you want

  2. in the OnTriggerStay() method, quickly fill it back up to maximum

Ultimately I understand you may want multiple places that trigger refill. In that case, once you have the above working, then make another completely-separate trigger-forwarding script that searches for this OxygenManager and calls the fill-it-back-up function. You can sprinkle this trigger forwarding script onto all your O2 fillup points on all levels.

This worked, thank you! I feel silly that I made it so complicated haha. Why would I use a trigger forwarding script instead of just attaching this script to the other O2 fillup areas?

    public GameObject oxygen;
    public Slider oxygenSlider;
    public bool losingOxygen;
    public float oxygenLoss;
    public float oxygenGain;

void OnTriggerEnter2D(Collider2D Collider)
    {
        if (Collider.gameObject.tag == "Player")

        {
          
            losingOxygen = false;
           
        }

    }



void OnTriggerStay2D(Collider2D Collider)
    {
        if (Collider.gameObject.tag == "Player")

        {
          
            losingOxygen = false;
           
        }

    }


void OnTriggerStay2D(Collider2D Collider)
    {
        if (Collider.gameObject.tag == "Player")

        {
          
            losingOxygen = true;
           
        }

    }

void Start()
    {
      
        oxygenSlider = oxygen.GetComponent<Slider>();
        myRigidbody = player.GetComponent<Rigidbody2D>();

      

    }

    // Update is called once per frame
    void Update()
    {
        if (losingOxygen)
            oxygenSlider.value -= oxygenLoss* Time.deltaTime;
        else
            oxygenSlider.value += oxygenGain * Time.deltaTime;
  

    }

Because your oxygen will drain faster and faster for every instance of this script you add!

1 Like

Oh thanks that’s good to know.

This is indeed kind of a fundamental point of instances of components: every time you add a script to a Unity GameObject, the Update() function in that script is run an extra time on that GameObject. If you drag the same slider into two that script on two separate GameObjects, that slider will be serviced either up or down by both GameObjects, which for the oxygen consumption I doubt is what you want.

1 Like