High score hell ! =p

Hi I didn’t want to ask for help was hoping to figure it on my own but I have spent 3 days in my down time trying to figure it out so I must have forgotten or not understood something haha ! I’m trying to implement a high score I have tried a few ways my self and had a google and just cant seem to get it working and staying with the way we calculate score in this session and destroy the gamesession script to reset the score. was wondering if anyone had any ideas how to go about it. id rather learn something form others here than just not do it and move on =D ? I have not deviated from the code make in the lessons and deleted all attempts so far so its all the course code for now.
thanks i appreciate any and all help =D

Hi Daniel,

What exactly do you mean by highscore? Or rather: How is it supposed to “work”?

Maybe the PlayerPrefs could be a solution for saving a couple of highscore values. Look them up in the Unity API. You are looking for SetInt and GetInt.

1 Like

ah yea I see that was not very explanative sorry. I am after a high score that just keeps track of your highest score this play through. so if you get say 10 points lose and the score resets, it will say 10 is the highest score you have got so far, then if you score 15 the next time it will show 15 as your new high score, but if you only scored 5 it would remain at 10. after quitting the game and re launching it will go back to default as if you have never played.

i have been playing with this bit of code in different ways to get it to work but have had no luck so i think i may be barking up the wrong tree about how to go about it
"
if (gameSession.currentScore > currentHighScore)
{
currentHighScore = gameSession.currentScore;
}

"

I will start looking into the bits you mentioned right now. Im super green at this so i only know really know what’s in the course up to this point =/. I wanted to push my self a bit on this one though and dint want to just not do it without seeing if I could learn something form the attempt heheh.

Right I have had a play around as far as I can tell the PlayerPrefs would be if I wanted it to save persistently (please correct me if I’m wrong I often am hahah )

so as far as I can see what I have set up should work but it still doesn’t seem to. I have created a second canvas with a TMP high score text attached, Basically the same as the canvas set up in the course for score but separate so it is not destroyed when we destroy the game session object to reset the score. so the high score should persist I hope =p.

so the high score should go up each time the score dose but only if its more than the last high score it received. I’m not so fussed about getting it working as much as understanding what I have misunderstood now =D. I will have a shot at attaching the scripts to this post (never done that before)

the new script not in the course is called High score and is attached to the high score canvas of the high score text so its not destroyed and doesn’t lose its links when we reset the score after losing

using TMPro;
using UnityEngine;

public class HighScore : MonoBehaviour
{
    // config Params
    [SerializeField] TextMeshProUGUI highScoreText;
    [SerializeField] int currentHighScore = 0;
    // cached reference
    GameSession gameSession;

    private void Awake()
    {
        int gameStatusCount = FindObjectsOfType<HighScore>().Length;
        if (gameStatusCount > 1)
        {
            gameObject.SetActive(false);
            Destroy(gameObject);
        }
        else
        {
            DontDestroyOnLoad(gameObject);
        }        
    }
    private void Start()
    {
        highScoreText.text = currentHighScore.ToString();
    }
   public void AddToHighScore()
    {
         currentHighScore += gameSession.pointsPerBlockDestroyed;
         highScoreText.text = currentHighScore.ToString();
         if (gameSession.currentScore > currentHighScore)
         {
          currentHighScore = gameSession.currentScore;
         }
   }
}
  

The next script is the game session script from the course not much has been altered except making one of the fields public so it could be used by high score

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

public class GameSession : MonoBehaviour
{
    // config Params
    [Range(0.1f, 10f)] [SerializeField] float gameSpeed = 1f;
    [SerializeField] public int pointsPerBlockDestroyed = 5;
    [SerializeField] TextMeshProUGUI scoreText;
    [SerializeField] bool isAutoPlayEnabled;
   
    //state Variables
    [SerializeField] public int currentScore = 0;
 
    private void Awake()
    {
        
        int gameStatusCount = FindObjectsOfType<GameSession>().Length;
        if (gameStatusCount > 1)
        {
            gameObject.SetActive(false);
            Destroy(gameObject);
        }

        else
        {
            DontDestroyOnLoad(gameObject);
        }
    }

    private void Start()
    {
      scoreText.text = currentScore.ToString();
    }
    // Update is called once per frame
    void Update()
    {
        Time.timeScale = gameSpeed;
    }


    public void AddToscore()
    {
        currentScore += pointsPerBlockDestroyed;
        scoreText.text = currentScore.ToString();

       
    }
    public void ResetScore()
    {
        Destroy(gameObject);
    }

    public bool IsAutoPlayEnabled()
    {
        return isAutoPlayEnabled;
    }
}

and the last one is the block scrip also from the course used to count the score when they are destroyed. this has been edited to be used by high score scrip to and to help the high score be increased

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

public class Block : MonoBehaviour
{
    //config params
    [SerializeField] AudioClip breakSound;
    [SerializeField] GameObject blockSparklesVFX;
    [SerializeField] Sprite[] hitSprites;
   
    // cached reference
    Level level;
  

    //state variables
    [SerializeField] int timesHit; // only serialised for debug

       private void Start()
    {        
        CountBreakableBlocks();
    }

    private void CountBreakableBlocks()
    {
        level = FindObjectOfType<Level>();
        if (tag == "Breakable")
        {
            level.CountBlocks();
        }
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (tag == "Breakable")
        {
            HandleHit();
        }
    }

    private void HandleHit()
    {
        timesHit++;
        int maxHits = hitSprites.Length + 1;
        if (timesHit >= maxHits)
        {
            DestroyBlock();
        }
        else
        {
            ShowNextHitSprite();
        }

    }

    private void ShowNextHitSprite()
    {
        int spriteIndex = timesHit - 1;
        if (hitSprites[spriteIndex] != null)
        { 
            GetComponent<SpriteRenderer>().sprite = hitSprites[spriteIndex];
        }
        else
        {
            Debug.LogError("Block Sprite is missing from array" + gameObject.name);
        }
    }

    private void DestroyBlock()
    {        
     playBlockDestroySFX();
     Destroy(gameObject);
     level.BlockDestroyed();
     TriggerSparklesVFX();
    }


    private void playBlockDestroySFX()
    {
        AudioSource.PlayClipAtPoint(breakSound, Camera.main.transform.position);
        FindObjectOfType<GameSession>().AddToscore();
        FindObjectOfType<HighScore>().AddToHighScore();
    }

    private void TriggerSparklesVFX()
    {
        GameObject sparkles = Instantiate(blockSparklesVFX, transform.position, transform.rotation);
        Destroy(sparkles, 2);
    }

sorry about the massive post and please let me know if I have done anything against the rules or etiquette in the way its posted. I really don’t post much. but any assistance or information on what my error is or what I have not quite understood would be very very welcome.
thanks in advance ( curranty it launches the ball hits a block the score goes up/ high score dose not then it crashes)

Good job on solving the problem, and thanks for sharing your code here. :slight_smile:

You are right. :slight_smile:

If you don’t need persistent highscores, a “pure” C# class will do the job. Unfortunately, I currently don’t have time to dive into the logic of your code but you could add a few Debug.Logs to see what’s going on.

Alternatively, you could try to write a “pure” C# class meaning a class that does not inherit from MonoBehaviour and does not get attached to your game objects. In that class, you could keep track of the score. Since it does not exist in the scene, it won’t get destroyed. Name it HighScore.

And another class could be responsible for displaying the data it got from the HighScore object. Name it HighScoreDisplay.

This way, you can keep the highscore logic and the display logic separate, which will make debugging a bit more convenient.

I’ve skimmed your code, though, and was not able to spot any problem which might result in a crash. Maybe I misunderstood your problem. What exactly do you mean by “crashes”? Are you getting any error messages? Does Unity freeze? If Unity freezes, there might be an endless loop somewhere.

1 Like

Right thanks so much I’m going to get stuck into that right now. I got a fair bit of work on this week but I will try and get it done before the post closes in 20days to put the code up for anyone it may help once its fixed. by crash I just meant a error that closes game mode not sure for the correct terminology for that hahah.

NullReferenceException: Object reference not set to an instance of an object
HighScore.AddToHighScore () (at Assets/Scripts/HighScore.cs:31)
Block.playBlockDestroySFX () (at Assets/Scripts/Block.cs:83)
Block.DestroyBlock () (at Assets/Scripts/Block.cs:72)
Block.HandleHit () (at Assets/Scripts/Block.cs:48)
Block.O

I think its because the block is destroyed before the HighScore script can read the the AddToHighScore mabe. really not sure but the scripts were defiantly attached to the correct game objects.
but i will try the ‘pure’ C# approach you have mentioned. although I will have a quick poke around with what i had already just to see what i can learn from it after your advice =D.

appreciate your time thanks I will let you know how I get on.
really enjoying the course

No need to hurry up. The thread is supposed to close 20 days after the last reply. That does not work, though. And even if it worked, we could reopen the thread if required.

NullReferenceException means that a reference (“link”) to an instance is missing. Double click on the error message to see to which line in your code it is referring.

One thing as it was not explicitely covered in the course: You can create a new object of your “pure” C# class with the new operator and the constructor. That’s very simple.

Furthermore, you will probably have to ensure that your other objects access the same HighScore object. This can be done with the singleton pattern by calling the Instance method. The first version on this website will do the job.

Alternatively, a static HighScore class with static methods and fields might be an idea since it’s more or less a unique and universal class.

The rest is just “normal” code as you already know it; minus the Unity specific methods and names.

1 Like

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

Privacy & Terms