Keep getting "object reference not set to instance of an object" in Unity

25 Views Asked by At

I am new to Unity and I am working on a car game project. I have pretty much finished the game however I would like to implement a leader board system in order for the user to see how well they've done in the past. I have already written the code to store all of this information in PlayerPrefs however I am not able to figure out why I am getting the error

NullReferenceException: Object reference not set to an instance of an object
CarController.Start () (at Assets/Scripts/CarController.cs:22)

Below is my "LeaderboardManager script which handles the processing of point data to turn it into a leader board:

using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using System.Linq;
using TMPro;
using static System.Net.Mime.MediaTypeNames;


public class LeaderboardManager : MonoBehaviour
{
    private const string highScoreKey = "highScores"; //Key for the player prefs reference 
    private const int maxScores = 10; //Constant for the maximum amount of high scores
    public List<int> highScores = new List<int>{};
    public TextMeshProUGUI leaderboardText; //Reference to the UI Text component
    MergeSort mergeSort = new MergeSort();

    void Start()
    {
        leaderboardText = GetComponentInChildren<TextMeshProUGUI>();
        if (!PlayerPrefs.HasKey(highScoreKey)) //Make new blank key in playerprefs if there isn't one already
        {
            PlayerPrefs.SetString(highScoreKey, "");
        }
        else //Load scores from playerprefs
        {
            string json = PlayerPrefs.GetString(highScoreKey); //Get string from player prefs storage
            highScores = JsonUtility.FromJson<List<int>>(json); //Convert string to list so merge sorts can be applied
        }
    }

    void Update()
    {
        updateUI();
    }

    private void saveScores()
    {
        string json = JsonUtility.ToJson(highScores); //Save list data type to json as a string so it can be stored
        PlayerPrefs.SetString(highScoreKey, json); //Sets the playerprefs string to the new json highscore value
        PlayerPrefs.Save(); //Saves the playerprefs file
    }

    public void addScore(int score)
    {
        highScores.Add(score);
        MergeSort.MergeSortRecursive(highScores); //Merge sorts the highscore list
        highScores = highScores.Take(maxScores).ToList(); //Takes only the first 10 values of the list and discards the rest
        saveScores(); //Writes scores to playerprefs file
    }

    public void updateUI()
    {
        leaderboardText.text = createUI();
    }

    private string createUI()
    {
        string text = "High Scores:\n";
        try
        {
            for (int i = 0; i < highScores.Count; i++)
            {
                text += $"{i + 1}. {highScores[i]}\n";
            }
        }
        catch { }
        return text;
    }

}

However this is where the problem arises.

I am trying to call the "addScore()" function from my Carcontroller script and this is where I am getting the error.

Carcrontroller Script:

using UnityEngine;
using UnityEngine.UI;

public class CarController : MonoBehaviour
{
    private bool isMoving = true;
    private bool hasCrossedIntersection = false;
    float points;
    CarSpawner carspawnerscript; //Reference to the carspawner script to toggle spawning when limit reached
    UIManager UIManager; //reference to the UImanager gameobject to toggle the end of game menu
    PointManager PointManager; //reference to the pointmanager to increment the points when the instanciated cars pass a point
    PointSaver PointSaver;
    public LeaderboardManager LeaderboardManager;

    void Start()
    {
        carspawnerscript = GameObject.FindGameObjectWithTag("GameController").GetComponent<CarSpawner>(); ////Assigns the gameobject of the carSpawner
        UIManager = FindObjectOfType<UIManager>(); //Assigns the UImanager gameObject
        PointManager = FindObjectOfType<PointManager>(); //Assigns the PointManager gameObject
        PointSaver = FindObjectOfType<PointSaver>();
        GameObject leaderboardObject = GameObject.Find("LeaderboardObject");
        LeaderboardManager = leaderboardObject.GetComponent<LeaderboardManager>();
    }


    void Update()
    {
        points = PointManager.points / 2;
        if (isMoving)
        {
            MoveCar(); //Calls function to move car
        }
        if (transform.position.x < 0.35f) // if the position of the car has crossed the intersection
        {
            hasCrossedIntersection = true;
        }
    }

    void MoveCar()
    {
        transform.Translate(Vector3.forward * Time.deltaTime * (1+(points/50))); //Unity's method of moving a rigidbody but adds a speed multiplier to increase difficulty as the game progresses
    }

    public void ToggleMovement(bool canMove)
    {
        isMoving = canMove; //toggles movement (public attribute)
    }

    void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("Intersection")) //Compares the collider tag to make sure the collision is with the intersection and stops the car accordingly
        {                                       //and that the intersection has not already been crossed
            if (hasCrossedIntersection == false)
            {
                ToggleMovement(false); 
            }
        }
        if (other.CompareTag("Car")) //compares the tag to stop the car if it collides with a car infront of it at the stop lights
        {
            ToggleMovement(false);
        }
        if (other.CompareTag("CollisionCar")) //comapre tag to check whether game-ending collision has occured
        {
            Invoke("endgame", 0);//Runs the subroutine delayedSpawn() after x seconds
        }
        if (other.CompareTag("CarLimitDetector"))//Stops spawning of cars when the queue of cars is full to aviod stacking of gameObjects
        {
            carspawnerscript.Spawntrue();
        }
        if (other.CompareTag("PointMod")) //Increments the points by 1 when the car passes a "checkpoint"
        {
            PointManager.IncrementPoints();
        }
    }

    void OnTriggerExit(Collider other)
    {
        if (other.CompareTag("Car")) //resumes the movement of the car when there is space infront of it afer a random amount of time specified
        {
            Invoke("ResumeMovement", UnityEngine.Random.Range(0.05f, 0.15f));//Invoke method used to delay
        }
        if (other.CompareTag("Intersection"))//Resumes movement when the intersection collider not present
        {
            Invoke("ResumeMovement", UnityEngine.Random.Range(0.001f, 0.07f));//Invoke method used to delay
        }
        if (other.CompareTag("CarLimitDetector"))
        {
            carspawnerscript.Spawntrue();//resumes spawning when there are less cars on the road
        }

    }
    void ResumeMovement()
    {
        ToggleMovement(true); //Resumes the movement of the car
    }

    void endgame()
    {
        Time.timeScale = 0; //pauses the game and shows the endgame menu
        UIManager.ShowEndGameMenu();
        if(PointSaver.checkhighscore(PointManager.points / 2))
        {
            PointSaver.savehighscore(PointManager.points / 2);
            PointManager.highscore = true;
            PointManager.UpdatePointsUI();
            LeaderboardManager.addScore(PointManager.points/2);
        }
    }
}

Both of the scripts are attached to a gameObject "LeaderboardManager" and "Car" respectively. The cars are instantiated by another script therefore I have no clue how to reference the LeaderboardManager script. Any help would be greatly appreciated.

I have tried referencing the LeaderboardManager numerous different ways and I was expecting the CarController to call the function "addScore()" in the LeaderboardManager gameObject. However as described above I got the error: "NullReferenceException: Object reference not set to an instance of an object CarController.Start () (at Assets/Scripts/CarController.cs:22)"

The game is carcross.co.uk for context

0

There are 0 best solutions below