Trying to reduce my lives int from another script

How could I reduce the amount of lives I have in a game based upon a collision with two different objects? I have a manager object to keep track of lives, but I want a life to be subtracted when two different objects collide. I’ll post my scripts below:

Object that I would like to subtract the life; specifically, where I placed the _gameManager.SubtractLife() method:

public class DeathBarrier : MonoBehaviour
{
    private GameManager _gameManager;

    private void Start()
    {
        GetComponent<GameManager>().SubtractLife();
    }
    private void OnCollisionEnter2D(Collision2D collision)
    {
        int NumberOfBallsLeft = FindObjectsOfType<Ball>().Length;
        if (collision.transform.CompareTag("Ball") && NumberOfBallsLeft > 1)
        {
            Destroy(collision.gameObject);
        }
        else if (collision.transform.CompareTag("Ball") && NumberOfBallsLeft <= 1)
        {
            _gameManager.SubtractLife();
            FindObjectOfType<Ball>().ResetPosition();
        }
        else if (collision.transform.CompareTag("Powerup"))
        {
            Destroy(collision.gameObject);
        }
    }
}

The game Manager itself:

namespace SampleGame
{
    public class GameManager : MonoBehaviour
    {
        #region LIVES
        // number of lives & images
        public GameObject heart1, heart2, heart3, heart4, heart5, gameover;
        public static int life;

        // are we alive?
        private bool dead;
        #endregion
        // reference to player
        private KeyboardControls _player;

        // reference to player
         private Level _level;

        private bool _isGameOver;
        public bool IsGameOver { get { return _isGameOver; } }

        private static GameManager _instance;
        public static GameManager Instance { get { return _instance; } }

       [SerializeField] private TransitionFader _endTransitionPrefab;

        // initialize references
        private void Awake()
        {
            life = 3;
            heart1.gameObject.SetActive(true);
            heart2.gameObject.SetActive(true);
            heart3.gameObject.SetActive(true);
            heart4.gameObject.SetActive(false);
            heart5.gameObject.SetActive(false);
            gameover.gameObject.SetActive(false);
            if (_instance != null)
            {
                Destroy(gameObject);
            }
            else
            {
                _instance = this;
            }

            _player = FindObjectOfType<KeyboardControls>();
            _level = FindObjectOfType<Level>();
        }

        private void OnDestroy()
        {
            if (_instance == this)
            {
                _instance = null;
            }
        }

        // end the level
       public void EndLevel()
        {
            if (_player != null)
            {
                // disable the player controls
                KeyboardControls keyboardControls =
                    _player.GetComponent<KeyboardControls>();

                if (keyboardControls != null)
                {
                    keyboardControls.enabled = false;
                }

                // remove any existing motion on the player
                Rigidbody rbody = _player.GetComponent<Rigidbody>();
                if (rbody != null)
                {
                    rbody.velocity = Vector3.zero;
                }
            }

            // check if we have set IsGameOver to true, only run this logic once
            if (!_isGameOver)
            {
                _isGameOver = true;
                StartCoroutine(WinRoutine());
            }
        }
       
        private IEnumerator WinRoutine()
        {
            TransitionFader.PlayTransition(_endTransitionPrefab);
            float fadeDelay = (_endTransitionPrefab != null) ? _endTransitionPrefab.Delay + _endTransitionPrefab.FadeOnDuration : 0f;
            yield return new WaitForSeconds(fadeDelay);
            WinScreen.Open();
        }

        // check for the end game condition on each frame
        private void Update()
        {
            {
                ParametersForDeath();
                if (dead == true)
                {
                    FindObjectOfType<SceneLoader>().LoadStartScene();
                }
            }
                if (life > 5)
            life = 5;

        switch (life)
        {

            case 5:
                heart1.gameObject.SetActive(true);
                heart2.gameObject.SetActive(true);
                heart3.gameObject.SetActive(true);
                heart4.gameObject.SetActive(true);
                heart5.gameObject.SetActive(true);
                gameover.gameObject.SetActive(false);
                break;
            case 4:
                heart1.gameObject.SetActive(true);
                heart2.gameObject.SetActive(true);
                heart3.gameObject.SetActive(true);
                heart4.gameObject.SetActive(true);
                heart5.gameObject.SetActive(false);
                gameover.gameObject.SetActive(false);
                break;
            case 3:
                heart1.gameObject.SetActive(true);
                heart2.gameObject.SetActive(true);
                heart3.gameObject.SetActive(true);
                heart4.gameObject.SetActive(false);
                heart5.gameObject.SetActive(false);
                gameover.gameObject.SetActive(false);
                break;
            case 2:
                heart1.gameObject.SetActive(true);
                heart2.gameObject.SetActive(true);
                heart3.gameObject.SetActive(false);
                heart4.gameObject.SetActive(false);
                heart5.gameObject.SetActive(false);
                gameover.gameObject.SetActive(false);
                break;
            case 1:
                heart1.gameObject.SetActive(true);
                heart2.gameObject.SetActive(false);
                heart3.gameObject.SetActive(false);
                heart4.gameObject.SetActive(false);
                heart5.gameObject.SetActive(false);
                gameover.gameObject.SetActive(false);
                break;
            case 0:
                heart1.gameObject.SetActive(false);
                heart2.gameObject.SetActive(false);
                heart3.gameObject.SetActive(false);
                heart4.gameObject.SetActive(false);
                heart5.gameObject.SetActive(false);
                gameover.gameObject.SetActive(true);
                Time.timeScale = 0;
                break;
        }
}
public void SubtractLife(){ life--; }
public void ParametersForDeath()
{
    if (life <= 0) { dead = true; }
    else { dead = false; }
}
public void AddLife()
{
    life++;
}
    }
}

You already appear to have a singleton setup for you GameManager, so just access it through that.

GameManager._instance.SubtractLife();

Otherwise, this code

GetComponent<GameManager>().SubtractLife();

Only works if the GameManager is on the same gameobject as the DeathBarrier script. There are ways to access it on other gameobjects, but just use the singleton instead.

1 Like

Ah I solved this by making my variable public and dragging the gameManager inside. So close!

Yep, that is another option, the downside to that is if you spawn something new in the scene, you can’t drag and drop during runtime, thus the purpose of the singleton.