Project Boost - Help, I want to create game over screen

Hi all, I’m trying to track how many times the rocket crashes and then use that to load a game over the screen. When I ever I play the crashCount is always 1. But never increases. Has anyone else had a go at this?

int crashCount = 0;


void StartCrashSequence()
    {
        if (crashCount == 3)
        {
            Invoke("GameOver", levelLoadDelay);
        }
        else
        {
           crashCount++;
            Debug.Log("Just a crash ----------->" + crashCount);
            isTransitioning = true;
            audioSource.Stop();
            audioSource.PlayOneShot(crashed);
            crashedParticles.Play();
            GetComponent<Movement>().enabled = false;
            Invoke("ReloadLevel", levelLoadDelay);

        }

Hi Nathaniel,

It’s great to see that you are challenging yourself, and your code looks fine so far. :slight_smile:

I assume you load a new level whenever StartCrashSequence gets called. If this object is not a ‘singleton’, it’ll get destroyed along with all non-persistent game objects in the Hierarchy. This means that the crashCount variable of this object gets destroyed as well, and your data gets lost.

A simple but rather bad solution would be to put the static access modifier in front of your variable declaration. It is bad because all objects of this type could modify this value. In this particular case, it does not matter, though, so you may test that. In larger projects, it is advisable to find another solution (e.g. a pure C# object or making this class ‘singleton’).

1 Like

I’ll be honest I don’t understand. I get that once the scene reloads it destroys any memory of the value of crashCount. So how do I get the reload to store the count

void ReloadLevel()
    {
        int currentSceneIndex = SceneManager.GetActiveScene().buildIndex;
        SceneManager.LoadScene(currentSceneIndex);
    }

There might be a better approach. In Kaan’s 2D Godot course, the first game is set up the same way; if you crash into a wall, the entire scene is reloaded as a quick-and-dirty way of resetting the player. That works perfectly fine when you don’t need anything persistent between impacts, but my extensions did.

Instead of reloading the scene, I just reset the player by manually setting its position values equal to that of a starting marker (just above the launch pad in your case). Because dynamic and kinematic movement don’t inherently mix well on the same object in Godot, that was trickier than it sounds (I’m not sure what the similar implications would be in Unity), but once I ironed it out, it worked fine.

As long as crashCount gets reset between levels, this might be something to try. If it’s not reset between levels, then I would recommend Nina’s idea of implementing a singleton instead, as singletons are persistent between scenes.

1 Like

Did you test the static access modifier? It connects the variable with the class instead of the instance. If the instance gets destroyed, the static variable continues to exist. If you create a new instance, that new instance has access to that static variable. That’s a quick and dirty solution. Test it to figure out if your current solution otherwise works as expected.

And if it works, you could look for a better solution than static. (Or keep static.)

I like @CoreyKnecht’s idea. You could store the player’s initial position and rotation values in two variables at the start of a new scene. Instead of reloading the scene, you simply override the player’s current position with the initial position, and the player’s current rotation with the initial rotation.

If you don’t want to reset the crashCount when a new level was loaded, the typical Unity ‘singleton’ would be a solution. Notice that I used ' ' because the Unity ‘singleton’ pattern is not the actual singleton pattern, so don’t try to implement any static methods such as Instance().

By the way, if you are interested in a free C# course, I can recommend Bob Tabor’s.

1 Like

Hi Guys, Update.

Yes I used @CoreyKnecht thinking around using the rocket as the reset and not the scene. manager when the rocket crashes. Also I set the crash count as a static

This im sure can be done better… Serialized field might be nice.

public static int crashCount = 1;
public static int youDead = 3;

Recorded rocket rotation & position, im sure there is a better way.

Vector3 startPosition;
Quaternion startRotation;

startPosition = gameObject.transform.position;
startRotation = gameObject.transform.rotation;

Update the crash method to check the crash count against youdead

if (crashCount == youDead)
        {
            Debug.Log("GAME OVER-----------------------" + crashCount);
            isTransitioning = true;
            audioSource.Stop();
            audioSource.PlayOneShot(crashed);
            crashedParticles.Play();
            GetComponent<Movement>().enabled = false;
            Invoke("GameOver", levelLoadDelay);
        }
        else
        {
            isTransitioning = true;
            audioSource.Stop();
            audioSource.PlayOneShot(crashed);
            crashedParticles.Play();
            GetComponent<Movement>().enabled = false;
            Invoke("ReloadLevel", levelLoadDelay);
        }

Then if crashCount matches youdead then run the below.

void GameOver()
    {
        Debug.Log("Load Game over screen");
        crashCount = 1;
        reStartGame();
    }

    void reStartGame()
    {
        SceneManager.LoadScene(0);
    }

It seems to be working. the next step will be to get the crashcount recorded on screen, add gameover screen and finally a timer!

Thanks for the help. Any additional advise will be welcome. I will post this update on the project chat as well.

1 Like

Good job! :slight_smile:

[SerializeField] just exposes a variable in the Inspector in Unity. Using it will not solve the problem because the problem is the instance variable getting destroyed when the instance gets destroyed. Since you cannot change the behaviour of C#, the solution is to keep the variable.

The last two lines must be executed in either Awake() or Start(), not at instance/class level. The variable declarations need to be at instance level. If this is what you did, your solution is exactly how one keeps values in an object as long as the object exists. :slight_smile:

It seems to be working. the next step will be to get the crashcount recorded on screen, add gameover screen and finally a timer!

That should be easy because, with public static, the variable is always accessible from all objects. (And this is also the reason why public static is usually ‘evil’, especially in large projects where you can easily get lots of problems if everything is able to modify everything.)

For now, I would suggest to make your ideas work first. Once everything works, make a backup of your project folder. Then try to get rid of public static if you want to implement a better solution.


See also:

2 Likes

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms