How do you add life just after completing a level?

im getting a red squiggly line in start under losecolider.numlives; hmmm

Aaw I’m sorry… :frowning:

Why is your int “static” what does it mean?

I’ll check my code tonight to see if I can help further

static means “relating to the type itself, rather than an instance of the type”. Static classes cannot have any instance members. i just removed static from script and looks like it did the trick just checking now for the moment of truth fingers crossed ha ha :grinning:

1 Like

if i remove static then i get red squiggly line in GameplayController script under (LoseColider.numLives) in Start

can you show the script please?

yep just a min

if i remove static then i get error here instead

hmm I don’t know how to work with static variables yet but what I would do is to reference the script LoseColider in your GameplayController like you did in the Level one, with FindObjectOfType.

perhaps i need to re do the whole lives system without static variables first

If you want to add a life after completing a level you gotta do something a little complex, first you gotta carry the number of lives the player has through each level, then you have to add a life. You could use the singleton pattern, or a scriptable object. I’ll use the singleton pattern in this case.

It would look something similar to this, you can use statics or not, it depends on what you need, but in this case, let’s forget about statics.

    private void Awake()
    {
        if (FindObjectsOfType<LivesCounter>().Length > 1)
        {
            Destroy(gameObject);
        }

        DontDestroyOnLoad(gameObject);
    }

This block of code prevents the object from being destroyed on level load, also prevents multiple copies of it existing on the same scene, we don’t want that.

Let’s add some more code to make it handle the lives.

    [SerializeField] int currentLives = 3; //The lives the player has

Just add a variable, this will be accessed in other scripts so we need a way to make it accesible. Since we know we’ll be adding and removing lives we need a method that gives us that kind of access.

public int AddLives (int livesToAdd) 
{ 
    currentLives += livesToAdd; 
    return currentLives;
}

This public method gives the ability to other scripts to modify the lives the player has.
This can be accessed from any script by doing something similar to this.

    private void GiveExtraLife()
    {
        FindObjectOfType< LivesCounter >().AddLives(1);
    }

You can do this from any script you want, that means that you can add power ups that gives extra lives, you can add enemies that remove lives and anything you like, at any time you want.

But here comes a question. Why are we returning an int value from the AddLives method? Because we need to know the value of the currentLives.

    private void LoseALife()
    {
        if(FindObjectOfType< LivesCounter >().AddLives(-1) <= 0);
        {
            //Lose the game.
        }
    }

As you can see in that code, we can modify and then access the value, two for one, Isn’t that cool? We are also removing a life by simply sending a negative value.

To add that extra life when a level loads you just gotta add it right before or right after loading a new scene. So basically call it on the Start or Awake method from another script, just be sure that is not the LivesCounter script. I mean, you could add it from the same LivesCounter script, but it’s a little convoluted and I don’t want to confuse you more.

    private void Start()
    {
        FindObjectOfType< LivesCounter >().AddLives(1);
    }

Here’s the whole LivesCounter script, you can use it as reference to modify your scripts or you could copy paste it and make the modifications needed in your other scripts.

using UnityEngine;

public class LivesCounter : MonoBehaviour
{
    [SerializeField] int currentLives = 3;

    private void Awake()
    {
        if (FindObjectsOfType<LivesCounter>().Length > 1)
        {
            Destroy(gameObject);
        }

        DontDestroyOnLoad(gameObject);
    }

    public int AddLives(int livesToAdd)
    {
        currentLives += livesToAdd;
        return currentLives;
    }
}

Hope this helps.

2 Likes

yes its does thankyou so much i shall give it my best shot

Here’s the code that automatically adds an extra life from the same script, for those that are curious as to how to achieve that, this uses something called Events, it’s a little complex, here’s the whole code and the documentation needed for anyone to understand what is going on.

Documentation:
https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager-sceneLoaded.html


using UnityEngine;
using UnityEngine.SceneManagement;

public class LivesCounter : MonoBehaviour
{
    [SerializeField] int currentLives = 3;

    private void Awake()
    {
        if (FindObjectsOfType<LivesCounter>().Length > 1)
        {
            Destroy(gameObject);
        }

        DontDestroyOnLoad(gameObject);
    }

    private void OnEnable()
    {
        SceneManager.sceneLoaded += ExtraLifeOnLoad;
    }

    private void ExtraLifeOnLoad(Scene scene, LoadSceneMode mode)
    {
        AddLives(1);
    }

    public int AddLives(int livesToAdd)
    {
        currentLives += livesToAdd;
        return currentLives;
    }

    private void OnDisable()
    {
        SceneManager.sceneLoaded -= ExtraLifeOnLoad;
    }
}

If any one wants me to add the Scriptable Object method I’ll gladly it write, it’s simpler but it comes with a somewhat annoying issue.

2 Likes

wow ! this is excellent thankyou so much

im lost here tbh might be a bit out of my depth

For Carre’s solution to work i would need to re do the lives system from scratch same way as Carre created his scripts. I followed tutorial on youtube but have found the lives system to be a problem when wanting to add extra life per level completion. Simply because the tutorial moved on to a coins based system which i didn’t want to do.

Yee gave me a lot of code and i really dont have a clue how to implement it correctly into my game. Ive played around with it but with no success. So im obviously doing it wrong.

I really appreciate the kind support. However, i still have not been able to create the add life to each level system in my game.

Its frusting :confused:

1 Like

Ok, to add an extra life per level is fairly simple. For this I’ll be using your old code.

Write this in your LoseColider script.

private void Start()
{
    if (SceneManager.GetActiveScene().name == "Level 1")
    {
        numLives = 3;
    }
    else //This is the new part
    {
        numLives += 1;
    }
}

There you have it, but there’s an issue, this won’t be carried away from level to level, so you’ll actually lose lives and start with just one life if the level loaded isn’t called “Level 1”. So we need a way to save this value. The easiest way to do this, is with an Scriptable Object, Remember those from the Text101 section? If not, go back to the lesson where they are introduced, it’s lesson 23. But worry not, I’ll write exactly what you need right here. Create a new script called Lives, erase everything inside it and copy-paste the code below, save afterwards:

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

[CreateAssetMenu(menuName = "Lives")]
public class Lives : ScriptableObject 
{
   public int numLives;
}

After you save this code, go to the editor and create a new “Lives” asset, it will be at the top of the menu.

Now we do need to make a lot of changes in your previous code, but nothing too complicated. In every place you are trying to access the lives you’ll need to write this.

[SerializeField] Lives lives;

After that you’ll have to set that variable in the editor, set it to the “Lives” asset you just created, there are some other small changes you’ll have to make, here’s an example on how the first block of code I wrote in this particular response should look like;

[SerializeField] Lives lives;

private void Start()
{
    if (SceneManager.GetActiveScene().name == "Level 1")
    {
        lives.numLives = 3;
    }
    else
    {
        lives.numLives += 1;
    }
}

And we are done, nothing too fancy. Just be aware, if you modify a Scriptable Object manually or via script during play time it will retain those values.

Just one final note, your code is a little messy, there are way too many scripts modifying and accessing the “numLives” variable, this is something you should try to avoid like the plague in your future projects.

1 Like

thankyou so much. yeh i know what you mean about there being too many scripts.

The scriptable object has Num Lives 0 do i leave it at 0 or change number. I have made an attempt at this process but had no success. So im doing it again

You can leave it as it is, since you’ll be modifying the number in code, of course you could add some extra lives just for testing purposes.

Privacy & Terms