Object reference not set to an instance of an object (824036)

Hello, I am making a pong game using 3D assets. If it helps at all to understand, here is an image for reference.


I am getting this error (below) when the ball collides either one of the goals (the two vertical walls).
6714598--771934--upload_2021-1-11_20-21-42.png
The following is my Ball script.

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

public class Ball : MonoBehaviour
{
    float _speed = 20f;
    int _points = 1000;
    Rigidbody _rigidbody;
    Vector3 _velocity;
    Renderer _renderer;

    void Start()
    {
        _rigidbody = GetComponent<Rigidbody>();
        _renderer = GetComponent<Renderer>();
        Invoke("Launch", 0.5f);
    }

    void Launch()
    {
        _rigidbody.velocity = Vector3.right * _speed;
    }

    void FixedUpdate()
    {
        _rigidbody.velocity = _rigidbody.velocity.normalized * _speed;
        _velocity = _rigidbody.velocity;
    }

    void Update()
    {

    }

    private void OnCollisionEnter(Collision collision)
    {
        _rigidbody.velocity = Vector3.Reflect(_velocity, collision.contacts[0].normal);

        Debug.Log("collision (name) : " + collision.collider.gameObject.name);

        if (collision.collider.name == "GoalRight")
        {
            GameManager.Instance.ScoreLeft += _points;
            Destroy(gameObject);
        }
        else if (collision.collider.name == "GoalLeft")
        {
            GameManager.Instance.ScoreRight += _points;
            Destroy(gameObject);
        }
      
    }
}

The following is my GameManager script.

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

public class GameManager : MonoBehaviour
{

    public static GameManager Instance { get; private set; }

    private int _scoreRight;

    public int ScoreRight
    {
        get { return _scoreRight; }
        set
        {
            _scoreRight = value;
            //scoreText.text = "SCORE: " + _scoreRight;
        }
    }

    private int _scoreLeft;

    public int ScoreLeft
    {
        get { return _scoreLeft; }
        set
        {
            _scoreLeft = value;
            //scoreText.text = "SCORE: " + _scoreLeft;
        }
    }

    void Start()
    {
      
    }

    void Update()
    {
        if (_scoreLeft == 10000 || _scoreRight == 10000)
        {
            Debug.Log("Left score is: " + _scoreLeft);
            Debug.Log("Right score is: " + _scoreRight);
        }
    }
}

The answer is always the same… ALWAYS. It is the single most common error ever. Don’t waste your life on this problem. Instead, learn how to fix it fast… it’s EASY!!

Some notes on how to fix a NullReferenceException error in Unity3D

  • also known as: Unassigned Reference Exception
  • also known as: Missing Reference Exception

http://plbm.com/?p=221

The basic steps outlined above are:

  • Identify what is null
  • Identify why it is null
  • Fix that.

Expect to see this error a LOT. It’s easily the most common thing to do when working. Learn how to fix it rapidly. It’s easy. See the above link for more tips.

This is the kind of mindset and thinking process you need to bring to this problem:

Step by step, break it down, find the problem.

1 Like

Thanks for your guidance. I already tried doing those steps and honestly I’m still quite lost. It is referring to the code GameManager.Instance.ScoreLeft += _points; (and the same for the right side), but that pathway exists in the GameManager. I have public static GameManager Instance { get; private set; }, private int _scoreRight; (and left), as well as the public int ScoreRight (and left) which can be seen in my code too. I can’t figure out why the code doesn’t see that and I’ve looked at each part and the variables seem to exist…

Look closely at GameManager code. Nothing in there actually sets the instance.

That’s the actual problem.

If you got this code from a tutorial, go back because you missed an important step.

If you are familiar with what a singleton is, these are the patterns I use for it when working in Unity3D:

Some super-simple Singleton examples to take and modify:

Simple Unity3D Singleton (no predefined data):

Unity3D Singleton with Prefab used for predefined data:

These are pure-code solutions, do not put anything into any scene, just access it via .Instance!

2 Likes

You need to set “Instance” to “this” somewhere in Awake or Start

Instance = this;

I did get it from a tutorial, however it was a tutorial that I completed and is now fully functioning. It’s a game that has quite similar mechanics (a breakout game). I basically tried to re-analyze the code from that and shift it over to what I’m trying to do in my pong game.

The game manager from their game looks like:

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

public class GameManager : MonoBehaviour
{
    public GameObject ballPrefab;
    public GameObject playerPrefab;
    public Text scoreText;
    public Text ballsText;
    public Text levelText;
    public Text highscoreText;

    public GameObject panelMenu;
    public GameObject panelPlay;
    public GameObject panelLevelCompleted;
    public GameObject panelGameOver;

    public GameObject[] levels;

    public static GameManager Instance { get; private set; }

    public enum State { MENU, INIT, PLAY, LEVELCOMPLETED, LOADLEVEL, GAMEOVER }
    State _state;
    GameObject _currentBall;
    GameObject _currentLevel;
    bool _isSwitchingState;

    private int _score;

    public int Score
    {
        get { return _score; }
        set { _score = value;
            scoreText.text = "SCORE: " + _score;
        }
    }

    private int _level;

    public int Level
    {
        get { return _level; }
        set { _level = value;
            levelText.text = "LEVEL: " + _level;
        }
    }

    private int _balls;

    public int Balls
    {
        get { return _balls; }
        set { _balls = value;
            ballsText.text = "BALLS: " + _balls;
        }
    }

    public void PlayClicked() // menu play is clicked
    {
        SwitchState(State.INIT);
    }

    void Start()
    {
        Instance = this;
        SwitchState(State.MENU);
        PlayerPrefs.DeleteKey("highscore");
    }

    public void SwitchState(State newState, float delay = 0)
    {
        StartCoroutine(SwitchDelay(newState, delay));
    }

    IEnumerator SwitchDelay(State newState, float delay)
    {
        _isSwitchingState = true;
        yield return new WaitForSeconds(delay);
        EndState();
        _state = newState;
        BeginState(newState);
        _isSwitchingState = false;
    }

    void BeginState(State newState)
    {
        switch (newState)
        {
            case State.MENU:
                Cursor.visible = true;
                highscoreText.text = "HIGHSCORE: " + PlayerPrefs.GetInt("highscore");
                panelMenu.SetActive(true);
                break;
            case State.INIT:
                Cursor.visible = false;
                panelPlay.SetActive(true);
                Score = 0;
                Level = 0;
                Balls = 3;
                if (_currentLevel != null)
                {
                    Destroy(_currentLevel);
                }
                Instantiate(playerPrefab);
                SwitchState(State.LOADLEVEL);
                break;
            case State.PLAY:
                break;
            case State.LEVELCOMPLETED:
                Destroy(_currentBall);
                Destroy(_currentLevel);
                Level++;
                panelLevelCompleted.SetActive(true);
                SwitchState(State.LOADLEVEL, 2f);
                break;
            case State.LOADLEVEL:
                if (Level >= levels.Length)
                {
                    SwitchState(State.GAMEOVER);
                }
                else
                {
                    _currentLevel = Instantiate(levels[Level]);
                    SwitchState(State.PLAY);
                }
                break;
            case State.GAMEOVER:
                if (Score > PlayerPrefs.GetInt("highscore"))
                {
                    PlayerPrefs.SetInt("highscore", Score);
                }
                panelGameOver.SetActive(true);
                break;
        }
    }

    void Update()
    {

        if (Input.GetKey ("escape"))
        {
            Application.Quit();
        }

        switch (_state)
        {
            case State.MENU:
                break;
            case State.INIT:
                break;
            case State.PLAY:
                if (_currentBall == null)
                {
                    if (Balls > 0)
                    {
                        _currentBall = Instantiate(ballPrefab);
                    }
                    else
                    {
                        SwitchState(State.GAMEOVER);
                    }
                }
                if (_currentLevel != null && _currentLevel.transform.childCount == 0 && !_isSwitchingState)
                {
                    SwitchState(State.LEVELCOMPLETED);
                }
                break;
            case State.LEVELCOMPLETED:
                break;
            case State.LOADLEVEL:
                break;
            case State.GAMEOVER:
                if (Input.anyKeyDown)
                {
                    SwitchState(State.MENU);
                }
                break;
        }
    }

    void EndState()
    {
        switch (_state)
        {
            case State.MENU:
                panelMenu.SetActive(false);
                break;
            case State.INIT:
                break;
            case State.PLAY:
                break;
            case State.LEVELCOMPLETED:
                panelLevelCompleted.SetActive(false);
                break;
            case State.LOADLEVEL:
                break;
            case State.GAMEOVER:
                panelPlay.SetActive(false);
                panelGameOver.SetActive(false);
                break;
        }
    }
}

And their ball looks like this:

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

public class Ball : MonoBehaviour
{
    float _speed = 20f;
    Rigidbody _rigidbody;
    Vector3 _velocity;
    Renderer _renderer;

    void Start()
    {
        _rigidbody = GetComponent<Rigidbody>();
        _renderer = GetComponent<Renderer>();
        Invoke("Launch", 0.5f);
    }

    void Launch()
    {
        _rigidbody.velocity = Vector3.up * _speed;
    }

    void FixedUpdate()
    {
        _rigidbody.velocity = _rigidbody.velocity.normalized * _speed;
        _velocity = _rigidbody.velocity;

        if (!_renderer.isVisible)
        {
            GameManager.Instance.Balls--;
            Destroy(gameObject);
        }
    }

    private void OnCollisionEnter(Collision collision)
    {
        _rigidbody.velocity = Vector3.Reflect(_velocity, collision.contacts[0].normal);
    }
}

Sorry I’m not the best at identifying the problem myself yet. I’m 16 and just learning how to code in c# during the past month, it’s honestly been a blast and I’ve been able to understand a lot more things on my own now but still trying to get the hang of it.

But yeah, I can’t see any components that could be missing from mine that theirs had. It appears that the only things used to make those “bigger variables” (I don’t know the right term lol) is that public static GameManager Instance { get; private set; } statement, the statement that defines the value, and the variable itself. I seem to have all of those pieces so I’m like, completely lost.

thank you so much!!! that fixed it!

I can relate to this a lot, haha, lucky for you there is much more availability this days to learn by yourself.
I think you’re talking about global/static variables when you say “bigger variables”, also learn about properties (that’s the {get; set;} thing)

if you’re looking for some all-round tutorials you can check out SebastianLague on youtube, that guy is a wizard and also have an introductory tutorial on his channel.
https://www.youtube.com/playlist?list=PLFt_AvWsXl0fnA91TcmkRyhhixX9CO3Lw

1 Like