Object Reference not set to an instance of an object

So I am making a Game Tutorial and I want to activate and deactivate parts of the scene depending on what I need. To disable all the buttons I made Object.Find("Add +1").SetActive(false); and then a debug to see that its working. After this later in the script in Game Tutorial wich is the same script I Said Object.Find("Add +1").SetActive(true); But when I tried it didn’t worked and it gave me this error : NullReferenceException: Object Reference not set to an instance of an object

What I can do?

Here is the full script:

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

public class RoboScript : MonoBehaviour
{
    public GameObject[] popUps;
    private int popUpIndex;
    public float waitTime = 5f;
    public int callGloba;

    private void Start()
    {
        GameObject.Find("Add +1").SetActive(false);
        Debug.Log("Add Has Been Disabled Succesfully");
        GameObject.Find("Extract -1").SetActive(false);
        Debug.Log("Extract -1 Has Been Disabled Succesfully");
        GameObject.Find("Show Number").SetActive(false);
        Debug.Log("Show Number Has Been Disabled Succesfully");
    }

    private void Update()
    {
        callGloba = Level2.yos;
        for (int i = 0; i < popUps.Length; i++)
        {
            if(i == popUpIndex)
            {
                popUps[i].SetActive(true);
            } else
            {
                popUps[i].SetActive(false);
            }
        }
        if (popUpIndex == 0)
        {
            if (Input.GetMouseButtonDown(0))
                {
                    popUpIndex++;
                }
        } else if (popUpIndex == 1)
        {
            GameObject.Find("Add +1").SetActive(true);
            Debug.Log("Add Has Been Enabled Succesfully");
            if (callGloba >= 1)
            {
                popUpIndex++;
            }
        }else if (popUpIndex == 2)
        {
            if (Input.GetMouseButtonDown(0))
            {
                popUpIndex++;
            }
        }else if (popUpIndex == 3)
        {
                if (callGloba == 0)
                {
                    popUpIndex++;
                }
        }
        else if (popUpIndex == 4)
        {
                if (callGloba >= 10)
                {
                    popUpIndex++;
                }
        }
    }
}

I’ll give this if needed
5892581--628388--upload_2020-5-24_18-9-26.png

gameobject.find only returns active game objects, it would be better if you kept a reference to the game object in a field

How I do that can you help me?

yes for example you can add on the top part of your script:

public class RoboScript : MonoBehaviour
{
    public GameObject[] popUps;
    private int popUpIndex;
    public float waitTime = 5f;
    public int callGloba;

//
  public GameObject addObj;

void Awake(){

addObj = GameObject.Find("Add +1");
}

and then replace all your GameObject.Find(“Add +1”); with

addObj.SetActive(false);
//or
addObj.SetActive(true);

except the one on void awake of course =)

But void awake is not the same thing as void Start?

no void awake is 1st and void start is 2nd

So basically I do this

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

public class RoboScript : MonoBehaviour
{
    public GameObject[] popUps;
    private int popUpIndex;
    public float waitTime = 5f;
    public int callGloba;
    public GameObject addObj;
    public GameObject addObj1;
    public GameObject addObj2;

    void Awake()
    {
        addObj = GameObject.Find("Add +1");
        addObj1 = GameObject.Find("Extract -1");
        addObj2 = GameObject.Find("Show Number");
    }

     void Start()
    {
        addObj.SetActive(false);
        addObj1.SetActive(false);
        addObj2.SetActive(false);
    }
    private void Update()
    {
        callGloba = Level2.yos;
        for (int i = 0; i < popUps.Length; i++)
        {
            if(i == popUpIndex)
            {
                popUps[i].SetActive(true);
            } else
            {
                popUps[i].SetActive(false);
            }
        }
        if (popUpIndex == 0)
        {
            if (Input.GetMouseButtonDown(0))
                {
                    popUpIndex++;
                }
        } else if (popUpIndex == 1)
        {
            addObj.SetActive(true);
            Debug.Log("Add Has Been Enabled Succesfully");
            if (callGloba >= 1)
            {
                popUpIndex++;
            }
        }else if (popUpIndex == 2)
        {
            if (Input.GetMouseButtonDown(0))
            {
                popUpIndex++;
            }
        }else if (popUpIndex == 3)
        {
                if (callGloba == 0)
                {
                    popUpIndex++;
                }
        }
        else if (popUpIndex == 4)
        {
                if (callGloba >= 10)
                {
                    popUpIndex++;
                }
        }
    }
}

It works!

1 Like

correct! be careful if you use this method the objects must start as active before you start the game. Because of that reason that gameobject.find only tracks active objects.

If you want an even better way you can drag them in the inspector and you dont need to set them in void awake

Alright, thanks! But may I ask you can you help me with 1 more thing?

yes of course

I am doing a Game Tutorial as I said and as you saw in the script in one line it says

if (Input.GetMouseButtonDown(0))

That is not from the first line. Anyway, the thing is that in the tutorial you need to press on a button but if I do with Input if you press anywhere on the screen you will get it done. How do I make it so that I can only press on the specific button if you want as reference the button is obj 3

hmm for clicking on buttons it would be better if you used the canvas UI feature, it is much better for buttons here is a nice tutorial:

if you still want to keep the same style as you have then you would need to put a collider on the obj3, and use a raycast from your mouse position and if it detects collision with your button it would trigger. But the canvas UI is much easier and better way aswell =)

What do you mean by canvas UI? I just need to make the player to only click the specific button and to not put as a click anything else but the button

ok ok if you want to keep the same style then you must:

first go on your obj3 and add a component box collider 2d, then go on inspector and checkmark “isTrigger”

then use this code:

if (Input.GetMouseButtonDown(0))
        {
            Vector2 worldPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            RaycastHit2D hit = Physics2D.Raycast(worldPoint, Vector2.zero);

            if (hit.collider == obj3 )
            {
               //code for clicking obj3
            }
        }

but it would be better if you used canvas UI =)

How do I use canvas UI. It’s not that I don’t want to but I am new and don’t understand things too much

Also I am running into a problem with the script you just sent me when i put inside the code for clicking obj3 i put popupindex++; so it continues but when I press on the button it gets stuck there

you can learn by watching that video its easy to learn

to check what is happening in the current code put some debug logs so you can see where its going wrong

The script doesn’t continue as intended. After its done with Input MouseButton (0) it should continue at the else if but insted its stuck where I put at Debug.Log(“Hi”) and it doesn’t continue What should I do?

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

public class RoboScript : MonoBehaviour
{
    public GameObject[] popUps;
    private int popUpIndex;
    public float waitTime = 5f;
    public int callGloba;
    public GameObject addObj;
    public GameObject addObj1;
    public GameObject addObj2;

     void Start()
    {
        addObj.SetActive(false);
        addObj1.SetActive(false);
        addObj2.SetActive(false);
    }
    private void Update()
    {
        callGloba = Level2.yos;
        for (int i = 0; i < popUps.Length; i++)
        {
            if(i == popUpIndex)
            {
                popUps[i].SetActive(true);
            } else
            {
                popUps[i].SetActive(false);
            }
        }
        if (popUpIndex == 0)
        {
            if (Input.GetMouseButtonDown(0))
                {
                    popUpIndex++;
                }
        } else if (popUpIndex == 1)
        {
            addObj.SetActive(true);
            if (callGloba >= 1)
            {
                popUpIndex++;
            }
        }else if (popUpIndex == 2)
        {
            addObj.SetActive(false);
            addObj2.SetActive(true);
            if (Input.GetMouseButtonDown(0))
            {
                Vector2 worldPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition);
                RaycastHit2D hit = Physics2D.Raycast(worldPoint, Vector2.zero);
                if (hit.collider == addObj2)
                {
                    popUpIndex++;
                    return;
                }
                Debug.Log("Hi");
            }
        }else if (popUpIndex == 3)
        {
            addObj.SetActive(false);
            addObj1.SetActive(true);
            if (callGloba == 0)
                {
                    popUpIndex++;
                }
        }
        else if (popUpIndex == 4)
        {
                if (callGloba >= 10)
                {
                    popUpIndex++;
                }
        }
    }
}

I tried with return; but it doesn’t work