After public object removal Null Reference Exception Error

Hello Everyone and Happy Holidays,

Just now I removed a seemingly unnecessary game objected called “empty” from my environment and commented respected commands in the script out. The specific code lines simply set a tag “active” and “untag” to the empty game object. I figured that I do not need this empty game object anymore as I used it for testing. I removed and commented the respective lines out (line: 29,126,203,224) in the main scrip at the bottom. However, when running the simulation now I receive the following error:

NullReferenceException: Object reference not set to an instance of an object
ReacherAgent.CollectObservations (Unity.MLAgents.Sensors.VectorSensor sensor) (at Assets/ML-Agents/Examples/Reacher/Scripts/ReacherAgent.cs:66)

I then examine line 66 of the Reacher Agent.cs, which collect the position of each active target:

sensor.AddObservation(active.transform.parent.localPosition);

This however seems fine to me.
Then I thought, maybe the coroutine used to wait out a few frames could cause this error. I set the number of frames to wait for the next action to zero, but I still obtain this error. Any suggestion on whats going on here and how I could fix it ?

Main Script:

[code=CSharp]using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using Random = UnityEngine.Random;


public class Game_Manager : MonoBehaviour
{
    public GameObject agent;
    public GameObject hand;

    // empty array of size 4 to collect target objects
    public GameObject[] targetObjects = new GameObject[4];

    // 4x4 matrix to initialize and determine activation status of targets
    Matrix4x4 sequence = new Matrix4x4();
    int gameSequence = 0;
    int failCounter = 0;
    public bool random_sequence = false;
    Color temp;

    float rewardToGive = 1;

    public GameObject parent;

    // Inter Stimulus Interval
    private IEnumerator coroutine;
    //public GameObject empty;
 

    void Start()
    {

    }
 
    public void init()
    {
        coroutine = CoroutineAction();
        // targetObjects = GameObject.FindGameObjectsWithTag("Target");

        int c = 0;
        foreach (Transform child in parent.transform)
        {
            if (child.tag == "Target")
            {
                targetObjects[c] = child.gameObject;
                c++;
            }
        }

        if (random_sequence == false)
        {
            // set empty game object "Random_Gen_Target" as parent of Agent
            agent.transform.parent = gameObject.transform;

            sequence = Matrix4x4.identity;

            //sets the GoalOn Object of first sphere to Target Active
            setFirstActive();
        }
        else if (random_sequence == true)
        {
            sequence = Yates.Shuffle(Matrix4x4.identity);
            Debug.Log(sequence);
            setFirstActive();
        }


    }

    // Initialize First Target activation:
    // Iterates over the first row and finds col i = 1
    private void setFirstActive()
    {
        for (int i = 0; i < 4; i++)
        {
            if (sequence[0, i] == 1)
            {
                // if condition fulfilled, set target to active
                targetObjects[i].transform.GetChild(0).gameObject.tag = "Active";
                //targetObjects[i].transform.GetChild(1).name = "Active";
            
                temp = targetObjects[i].GetComponent<Renderer>().material.color;
                targetObjects[i].GetComponent<Renderer>().material.color = new Color(224, 224, 224);
            }
        }
    }

    // for each round check which target is active
    int checkActive(int round)
    {
        for (int j = 0; j < 4; j++)
        {
        
            if (sequence[round, j] == 1)
            {
                return j;
            }
        }
        return 0;
    }
 
    public void triggered(GameObject touchedSphere)
    {
        // if more than than 1 target object
        if (targetObjects.Length > 1)
        {
            // Debug.Log("Touched = " + touchedSphere);
            // Debug.Log("active Object = " + targetObjects[checkActive(gameSequence)]);
            if (touchedSphere == targetObjects[checkActive(gameSequence)])
            {
                // and reward if correct target has been touched
                //agent.GetComponent<ReacherAgent>().AddReward(1.0f);
                agent.GetComponent<ReacherAgent>().AddReward(rewardToGive);

                Debug.Log("rewarded by " + rewardToGive);            
                gameSequence++;
                rewardToGive = 1.0f;
                failCounter = 0;
                // sets the tag of GoalOn objct of the touchedSphere to Untagged
                touchedSphere.transform.GetChild(0).gameObject.tag = "Untagged";
                // touchedSphere.transform.GetChild(1).name = "Unactive";
                // set the color of the target back to its original
                touchedSphere.GetComponent<Renderer>().material.color = temp;
                // empty.tag = "Active";
                StartCoroutine(CoroutineAction());
            }
            else
            {
                // if wrong sphere fail counter increments
                failCounter++;
                //TODO: fail increment per frame. needs to be reduced to 1 touch per collision
            }
        }
    }

    public GameObject getActive()
    {
        return GameObject.FindGameObjectsWithTag("Active")[0];
    }

    private void initializeNewRound()
    {
        sequence = Matrix4x4.identity;
        sequence = Yates.Shuffle(sequence);
        setFirstActive();
        //Debug.Log(sequence);
    }

    private void initializeFixedRound()
    {
        sequence = Matrix4x4.identity;
        setFirstActive();
        //Debug.Log(sequence);
    }

    void Update()
    {
        // every frame find and collect Targets
        // targetObjects = GameObject.FindGameObjectsWithTag("Target");
        int c = 0;
        foreach (Transform child in parent.transform)
        {
            if (child.tag == "Target")
            {
                targetObjects[c] = child.gameObject;
                c++;
            }
        }

        rewardToGive = rewardToGive * 0.99f;
        rewardToGive = Math.Max(0.1f, rewardToGive);

        float noise = Noise.gauss(0,0.01);
        // empty.transform.localPosition = new Vector3(0 + noise, -4 + noise, 0 + noise);
    }

    // Counts frames for the intertrial interval
    public static class WaitFor
    {
        public static IEnumerator Frames(int frameCount)
        {

            while (frameCount > 0)
            {
                frameCount--;
                yield return null;
            }
        }
    }

    // Coroutine defines the scheduling or execution time of code during the intertrial interval
    public IEnumerator CoroutineAction()
    {

        if (gameSequence > 3)
        {
            gameSequence = 0;
            failCounter = 0;

            yield return StartCoroutine(WaitFor.Frames(0)); // wait for 20 frames
            //empty.tag = "Untagged";
            //Debug.Log(gameSequence);

            // Start a new round
            // initializeNewRound();

            if (random_sequence == false)
            {
                initializeFixedRound();
            }
            else if (random_sequence == true)
            {
                initializeNewRound();
            }
        }

        // else if it is not the last ball
        else
        {
            yield return StartCoroutine(WaitFor.Frames(0)); // wait for 20 frames
                                                         
            //empty.tag = "Untagged";
            // Debug.Log(gameSequence);
            int active = checkActive(gameSequence);
            // sets the tag of the next balls GoalOn objct Active
            targetObjects[active].transform.GetChild(0).gameObject.tag = "Active";
            // targetObjects[active].transform.GetChild(1).name = "Active";
            // save its color to temp
            temp = targetObjects[checkActive(gameSequence)].GetComponent<Renderer>().material.color;
            // let it light up
            targetObjects[active].GetComponent<Renderer>().material.color = new Color(224, 224, 224);

        }

    }

}

You found the line that causes the NullReferenceException. Check what there is null. Is it ‘sensor’? Is it ‘active’? Is it maybe that ‘active’ does not have a parent? Should be one of those.

Hey thank you. I am new to this whole thing with unity. How can I check it ?
Also the code works however, after touching the second active target, it returns the error. So I am not sure if its because of the parent command. It seems to work for 2 instances. This is the architecture of each parent and child object in the environment.
6671611--763834--Screen Shot 2020-12-30 at 15.16.34.png

You can use Debug.Log() to print information to the console. Use this to get additional information about a problem. In your case, you can, for example, print Debug.Log("Is sensor null: " + sensor == null); and also for the others.

Try to find out what specifically is null, and when it is null.
Then you can reason about why that is, and then fix that.

Thank you Yoreki, I will try this out. :slight_smile: Happy holidays.

1 Like

Exactly what he says above… it’s the only way. Here is my standard blurb for nullref:

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:

https://discussions.unity.com/t/814091/4

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

1 Like