NullReferenceException: Object reference not set to an instance of an object GameManager.Spawn...

Hi guys !

I am new to scripting and I tried to follow this tutorial and apply it to my own game.
My problem is I have this error in unity :

"NullReferenceException: Object reference not set to an instance of an object
GameManager.SpawnAllWarlocks () (at Assets/Script/GameManager.cs:37)
GameManager.Start () (at Assets/Script/GameManager.cs:27) "

Here is my code :

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

public class GameManager : MonoBehaviour {

    public int numRoundsToWin = 5;
    public float startDelay = 3f;
    public float endDelay = 3f;
    public CameraController cameraController;
    public Text messageText;
    public GameObject warlockPrefab;
    public WarlockManager[] warlocks;

    private int roundNumber;
    private WaitForSeconds startWait;
    private WaitForSeconds endWait;
    private WarlockManager roundWinner;
    private WarlockManager gameWinner;

    void Start () {
        startWait = new WaitForSeconds(startDelay);
        endWait = new WaitForSeconds(endDelay);


        SpawnAllWarlocks();
        SetCameraTargets();

        StartCoroutine(GameLoop());
      
    }

    private void SpawnAllWarlocks()
    {

        for (int i = 0; i < warlocks.Length; i++)
        {
            warlocks[i].instance = Instantiate(warlockPrefab, warlocks[i].spawnPoint.position, warlocks[i].spawnPoint.rotation) as GameObject;
            warlocks[i].playerNumber = i + 1;
            warlocks[i].Setup();
        }
    }
  
    private void SetCameraTargets()
    {
        Transform[] targets = new Transform[warlocks.Length];

        for (int i = 0; i < targets.Length; i++)
        {
            targets[i] = warlocks[i].instance.transform;
        }

        cameraController.m_Targets = targets;
    }

    private IEnumerator GameLoop()
    {
        yield return StartCoroutine(RoundStarting());
        yield return StartCoroutine(RoundPlaying());
        yield return StartCoroutine(RoundEnding());

        if (gameWinner != null)
        {
            SceneManager.LoadScene(0);
        }
        else
        {
            StartCoroutine(GameLoop());
        }
    }

    private IEnumerator RoundStarting()
    {
        ResetAllWarlocks();
        DisableWarlockControl();
        //cameraController.SetStartPositionAndSize();

        roundNumber++;
        messageText.text = "ROUND " + roundNumber;

        yield return startWait;
    }

    private IEnumerator RoundPlaying()
    {
        EnableWarlockControl();

        messageText.text = string.Empty;

        while (!OneWarlockLeft())
        {
            yield return null;
        }
    }

    private IEnumerator RoundEnding()
    {
        DisableWarlockControl();
        roundWinner = null;
        roundWinner = GetRoundWinner();

        if (roundWinner != null)
            roundWinner.wins++;

        gameWinner = GetGameWinner();

        string message = EndMessage();
        messageText.text = message;

        yield return endWait;
    }
    private bool OneWarlockLeft()
        {
            int numWarlockLeft = 0;

            for (int i = 0; i < warlocks.Length; i++)
            {
                if (warlocks[i].instance.activeSelf)
                    numWarlockLeft++;
            }

            return numWarlockLeft <= 1;
        }


    private WarlockManager GetRoundWinner()
    {
        for (int i = 0; i < warlocks.Length; i++)
        {
            if (warlocks[i].instance.activeSelf)
                return warlocks[i];
        }
        return null;
    }

    private WarlockManager GetGameWinner()
    {
        for (int i = 0; i < warlocks.Length; i++)
        {
            if (warlocks[i].wins == numRoundsToWin)
                return warlocks[i];
        }
            return null;
    }

    private string EndMessage()
    {
        string message = "DRAW!";

        if (roundWinner != null)
            message = roundWinner.coloredPlayerText + " WINS THE ROUND!";

        message += "\n\n\n\n";

        for (int i = 0; i < warlocks.Length; i++)
        {
            message += warlocks[i].coloredPlayerText + ": " + warlocks[i].wins + " WINS\n";
        }

        if (gameWinner != null)
            message = gameWinner.coloredPlayerText + " WINS THE GAME!";

        return message;
    }
// Update is called once per frame

    private void ResetAllWarlocks()
    {
        for (int i = 0; i < warlocks.Length; i++)
        {
            warlocks[i].Reset();
        }
    }


    private void EnableWarlockControl()
    {
        for (int i = 0; i < warlocks.Length; i++)
        {
            warlocks[i].EnableControl();
        }
    }


    private void DisableWarlockControl()
    {
        for (int i = 0; i < warlocks.Length; i++)
        {
            warlocks[i].DisableControl();
        }
    }
}

From what I’ve read so far, it seems that warlocks.Length returns null but I can’t be so sure since

if (warlocks.Length == null)
Debug.Log("Hello");

returns nothing in console.

From this point, I don’t know how to debug this.
May you help me please ? :slight_smile:

Did you drag your warlock prefab onto the place in the editor for it? When you click on your manager object, you should see the script, and then see the heading to drag it to.

Did you add the WarlockManager object to the slot in the inspector for warlocks?

Yes I did ! : Screenshot by Lightshot

you should also be seeing Warlocks under warlock prefab.
Verify the script has been saved. Then restart Unity and VS

I just restarted everything… I should be seeing Warlocks while inspecting GameManager object right under " Warlock Prefab " ?

If so, I don’t see it

Well that’s a problem. because that means warlocks is null, and that’s why you’re getting the errors.
What gameobject is the script warlockManager attached to? From what I can see in the GameManger script. Each warlock has this script attached to it. Does WarlockPrefab have this script?
If so then do this

void Start () {
        startWait = new WaitForSeconds(startDelay);
        endWait = new WaitForSeconds(endDelay);
        warlocks.Add(warlockPrefab); //this will add the object to the array,  what this is for a List<>,  edit coming soon, hold on.
        SpawnAllWarlocks();
        SetCameraTargets();
        StartCoroutine(GameLoop());
  
    }

update

void Start () {
        startWait = new WaitForSeconds(startDelay);
        endWait = new WaitForSeconds(endDelay);
        warlocks = new WarlockManager[1]; //I'm forcing an array length of 1
        warlocks[0] = warlockPrefab; //pushing the gameobject to the array
        SpawnAllWarlocks();
        SetCameraTargets();
        StartCoroutine(GameLoop());
    
    }

WarlockManager isn’t attached to any gameObject since it is [SerializeField] and not MonoBehavior (from what I understood in the tutorial …)

here is he WarlockManager Script :

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

[SerializeField]
public class WarlockManager {

    public Color playerColor;
    public Transform spawnPoint;
    [HideInInspector] public int playerNumber;
    [HideInInspector] public string coloredPlayerText;
    [HideInInspector] public GameObject instance;
    [HideInInspector] public int wins;

    private PlayerController movement;
    private PlayerShooting shooting;
    private GameObject canvasGameObject;

    public void Setup()
    {

        movement = instance.GetComponent<PlayerController>();
        shooting = instance.GetComponent<PlayerShooting>();
        canvasGameObject = instance.GetComponentInChildren<Canvas>().gameObject;

        movement.playerNumber = playerNumber;
        shooting.playerNumber = playerNumber;

        coloredPlayerText = "<color=#" + ColorUtility.ToHtmlStringRGB(playerColor) + ">PLAYER" + playerNumber + "</Color>";

        MeshRenderer[] renderers = instance.GetComponentsInChildren<MeshRenderer>();

        for (int i = 0; i < renderers.Length; i++)
        {
            renderers[i].material.color = playerColor;
        }
    }

    public void DisableControl()
    {
        movement.enabled = false;
        shooting.enabled = false;

        canvasGameObject.SetActive(false);
    }

    public void EnableControl()
    {
        movement.enabled = true;
        shooting.enabled = true;

        canvasGameObject.SetActive(true);
    }

    public void Reset()
    {
        instance.transform.position = spawnPoint.position;
        instance.transform.rotation = spawnPoint.rotation;

        instance.SetActive(false);
        instance.SetActive(true);
    }
}

Sorry man, it’s over my head.
Why are there 3 variables that use WarlockManager? 1 is an array, 2 are not(roundWinner and gameWinner). I don’t see anything that sets the array. WarlockManager isn’t referencing back to GameManager.
maybe @Brathnann or @methos5k can take a look at this

1 Like

Interesting note, I found this page by mistake, and not by notification. heh.

Okay, so I took a quick look at the tutorial, and you want “System.Serializable”" for the class, not SerializeField

Next up, on an informative note, the WarlockManager array is for both tanks, and the round/game winner are for the individual tanks, I believe. (sorry warlocks, not tanks lol)

Thanks a lot for your help guys !

Works better with “System.Serializable” !
I still have the NullReferenceException though but i’m working on it !

Cool. By the way, if you add “using System;” at the top of your script, you can shorten that to “Serializable”.
Not that important, just thought I’d point it out, if you didn’t know.

Sounds good. Keeping trying/working on it, and if you’re still stuck later, feel free to post a follow up …

null reference is just a matter of identifying which variable and why and then making sure it’s … well, “there” rather than missing :wink:

Good luck :slight_smile:

1 Like