Any Idea why this doesn't work?

Anyone any Idea why the code from the lecture works but mine doesn’t? The score doesn’t get updated while playing but he will update the score on the next playtest. Ricks version works fine.

My Version with the GameSession referenced in a SerializedField and it should behave the same way, at least i think so :smiley: :

public class CoinPickup : MonoBehaviour
{
    [SerializeField] GameSession gameSession;

    [SerializeField] AudioClip coinPickupSFX;
    [SerializeField] int coinValue = 100;

    void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.tag == "Player")
        {
            IncreaseScoreCount();
            AudioSource.PlayClipAtPoint(coinPickupSFX, Camera.main.transform.position, 0.5f);
            Destroy(gameObject);
        }
    }

    void IncreaseScoreCount()
    {
        gameSession.IncreaseGameScore(coinValue);
    }
}

Ricks version from the course where he searches for GameSession via FindObjectOfType:

    [SerializeField] AudioClip coinPickupSFX;
    [SerializeField] int coinValue = 100;

    void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.tag == "Player")
        {
            FindObjectOfType<GameSession>().IncreaseGameScore(coinValue);
            AudioSource.PlayClipAtPoint(coinPickupSFX, Camera.main.transform.position, 0.5f);
            Destroy(gameObject);
        }
    }

Pictures of the code:

Mine:

Ricks:

So long as it’s all hooked up right, I’d guess the issue is in the GameSession class. CoinPickup looks fine - assuming it’s hooked up right and you’re getting no errors in the console.

That all being said, there’s a benefit to doing what you’re doing (taking code and improving on it) but there’s a benefit from learning the problem solving side of it. If you’re going to ask for help, it’s important to post all the details… the “Help me help you” kind of thing. In this one, you’ve left out one part of the problem which makes it tough to solve.

One last thing I’m going to throw out there. Defensive programming can help with these kinds of things.

Take for instance:

[SerializeField] GameSession gameSession;

void Start()
{
  if (gameSession == null)
    gameSession = FindObjectOfType<GameSession>();
}

So even if you don’t hook it up, the code will both help deal with those kinds of issues and also increases reusability of your code.

1 Like

Hello Michael, thanks for the feedback.

Console isn’t saying anything and the IncreaseScoreCount from my GameSession is getting called but doesn’t update the score on the scoreText TextMeshPro when playing. The slightly different version from Rick works fine and i would like to understand what the difference is.

My GameSession.cs

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

public class GameSession : MonoBehaviour
{
    [SerializeField] int playersLives = 3;

    [SerializeField] TextMeshProUGUI livesText;
    [SerializeField] TextMeshProUGUI scoreText;
    [SerializeField] int playerScore;



    void Awake()
    {
        int numGameSessions = FindObjectsOfType<GameSession>().Length;

        if (numGameSessions > 1)
        {
            Destroy(gameObject);
        }
        else
        {
            DontDestroyOnLoad(gameObject);
        }
    }

    void Start()
    {
        livesText.text = playersLives.ToString();
        scoreText.text = playerScore.ToString();
    }

    public void ProcessPlayerDeath()
    {
        if(playersLives > 1)
        {
            TakeLife();
        }
        else
        {
            ResetGameSession();
        }
    }

    void TakeLife()
    {
        playersLives--;
        int currentSceneIndex = SceneManager.GetActiveScene().buildIndex;
        SceneManager.LoadScene(currentSceneIndex);
        livesText.text = playersLives.ToString();
    }

    void ResetGameSession()
    {
        playerScore = 0;

        SceneManager.LoadScene(0);
        Destroy(gameObject);
    }

    public void IncreaseGameScore(int coinValue)
    {
        Debug.Log("IncreaseGameScore called");
        playerScore += coinValue;
        scoreText.text = playerScore.ToString();
    }
}

And the Coin Prefab is setup like this, also checked if they are correct in the scene, which they seem to be:

Code looks about right. I assume it’s all hooked up correctly?

Does you Debug.Log go off each time you’d expect it to go off?

    public void IncreaseGameScore(int coinValue)
    {
        playerScore += coinValue;
        Debug.Log($"IncreaseGameScore to {playerScore}");
        scoreText.text = playerScore.ToString();
    }

Change your code to this so you can see if the logic is working as intended.

But it looks like everything is right. Perhaps the font size is too big to be shown in your scoreText area… or the scoreText is outside the visible screen?

It could be something I overlooked. What do you suspect is the cause?

1 Like

Tried your Debug.Log and some things that i noticed are, that execution seems to be right but he doesn’t update the TMPro. But the value between playtesting is still stored, even if i set it to 1 OnAwake in GameSession.cs.

Could this weird behavior come from the fact that the GameSession is moved to DontDestroyOnLoad while playtesting and he looses his reference or something? In Ricks version he searches for the GameSession OnAwake so he would find the correct one. Thats the only difference i can think off after a few hours :smiley:

Rick’s version has a problem with it that would occur beyond the first level though.

This line in awake

Destroy(gameObject);

Should read like this:

Destroy(gameObject);
gameObject.SetActive(false);

That’s probably why he searches for GameSession whenever he needs it. Because the reference from Awake won’t work right in some cases as he’s written it.

This is because there’s a delay in destroying an object so if you search for the GameSrssion in the first frame and there’s two of them, you may find the right one before it destroys itself. The SetActive(false) prevents that.

1 Like

In your case, you may be having problems beyond the first level if you are saving the GameSession from the 2nd level and using that. Because that is a brand new fresh GameSession with no data.

All of your data is still stored in the 1st level GameSession so you have to use that one, not the one from 2nd level.

If you have a GameSession in your 2nd level hierarchy and you are carrying one over from the 1st level, then during your first frame on level 2, you will have two GameSessions. At the end of that frame, the newest GameSession (level 2 Game Session) should destroy itself, per it’s Awake instructions.

That means you should be getting null reference errors when trying to use the reference to the level 2 Game Session. However, if you try to Find a new GameSession after the first frame, you will only find the Level 1 GameSession remaining, which is the correct one that has your score information from the previous levels.

Finding from the first frame will only yield the correct result if you implement the change I suggested in the post above (which comes from Sam, btw).

1 Like

Never occured to me to start from Level 1… damn. Yeah i’m getting a null reference error now and the script actually works on the first level, until i die or change to the second one, due to the null reference error.

At least i know what the problem is now and can try to find a solution for it, was driving me crazy that i had no clue at all what was wrong :smiley:

Thanks guys!

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

Privacy & Terms