NRE encountered when clicking on ground - debugging for an RTS game

Hello, I just started working with Unity and scripting in general, I am new to this realm so please bear with me.

I am trying to make an RTS game, following some tutorial on Youtube and landed on an issue that is quite frustrating. When I click on the ground in the Active game window without having a unit selected I get:

NullReferenceException: Object reference not set to an instance of an object
InputManager.LeftClick () (at Assets/Scripts/InputManager.cs:53)
InputManager.Update () (at Assets/Scripts/InputManager.cs:34)

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

public class InputManager : MonoBehaviour {
   
    public float panSpeed;
    public float rotateSpeed;
    public float rotateAmount;

    private Quaternion rotation;

    private float panDetect = 15f;
    private float minHeight = 10f;
    private float maxHeight = 100f;

    public GameObject selectedObject;
    public ObjectInfo selectedInfo;

    // Start is called before the first frame update
    void Start()
    {
        rotation = Camera.main.transform.rotation;
    }

    // Update is called once per frame
    void Update()
    {
        MoveCamera();
        RotateCamera();

        if(Input.GetMouseButtonDown(0))
        {  
            LeftClick();
        }

        if(Input.GetKeyDown(KeyCode.Space))
        {
            Camera.main.transform.rotation = rotation;
        }
    }

    public void LeftClick()
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;

        if(Physics.Raycast(ray, out hit, 100))
        {
            if(hit.collider.tag == "Ground")
            {
                selectedObject = null;
                selectedInfo.isSelected = false;
                selectedInfo = null;
                Debug.Log("Deselected");
            }
           
            else if(hit.collider.tag == "Selectable")
            {
                selectedObject = hit.collider.gameObject;
                selectedInfo = selectedObject.GetComponent<ObjectInfo>();

                selectedInfo.isSelected = true;

                Debug.Log("Selected" + selectedInfo.objectName);
            }
        }
    }

    void MoveCamera()
    {
        float moveX = Camera.main.transform.position.x;
        float moveY = Camera.main.transform.position.y;
        float moveZ = Camera.main.transform.position.z;

        float xPos = Input.mousePosition.x;
        float yPos = Input.mousePosition.y;

        if(Input.GetKey(KeyCode.A) || xPos > 0 && xPos < panDetect)
        {
            moveX -= panSpeed;
        }
        else if(Input.GetKey(KeyCode.D) || xPos < Screen.width && xPos > Screen.width - panDetect)
        {
            moveX += panSpeed;
        }

        if(Input.GetKey(KeyCode.W) || yPos < Screen.height && yPos > Screen.height - panDetect)
        {
            moveZ += panSpeed;
        }
        else if(Input.GetKey(KeyCode.S) || yPos > 0 && yPos < panDetect)   
        {  
            moveZ -= panSpeed;
        }


        moveY -= Input.GetAxis("Mouse ScrollWheel") * (panSpeed * 20);
        moveY = Mathf.Clamp(moveY, minHeight, maxHeight);   
        Vector3 newPos = new Vector3(moveX, moveY, moveZ);
        Camera.main.transform.position = newPos;

    }

    void RotateCamera()
    {
        Vector3 origin = Camera.main.transform.eulerAngles;
        Vector3 destination = origin;

        if (Input.GetMouseButton(2))
        {
            destination.x -= Input.GetAxis("Mouse Y") * rotateAmount;
            destination.y -= Input.GetAxis("Mouse X") * rotateAmount;
        }

        if (destination != origin)
        {
            Camera.main.transform.eulerAngles = Vector3.MoveTowards(origin, destination, Time.deltaTime * rotateSpeed);

        }
    }

}

This is the script in which the Error happens, and the following one has references that are used in the one above:

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

public class ObjectInfo : MonoBehaviour
{
    public TaskList task;
    public ResourceManager RM;

    public GameObject targetNode;

    public NodeManager.ResourceTypes heldResourceType;

    public bool isSelected = false;
    public bool isGathering = false;

    public string objectName;

    private NavMeshAgent agent;

    public int heldResource;
    public int maxHeldResource;

    public GameObject[] drops;



    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine(GatherTick());
        agent = GetComponent<NavMeshAgent>();
    }

    // Update is called once per frame
    void Update()
    {
        if(targetNode == null)
        {
            if(heldResource != 0)
            {
                drops = GameObject.FindGameObjectsWithTag ("Drops");
                agent.destination = GetClosestDropOff(drops).transform.position;
                drops = null;
                task = TaskList.Delivering;
            }
            else
            {
                task = TaskList.Idle;
            }
        }
        if(heldResource >= maxHeldResource)
        {
            drops = GameObject.FindGameObjectsWithTag ("Drops");
            agent.destination = GetClosestDropOff(drops).transform.position;
            drops = null;
            task = TaskList.Delivering;
        }


        if(Input.GetMouseButtonDown(1) && isSelected)
        {
            RightClick();
        }
    }

    GameObject GetClosestDropOff(GameObject[] dropOffs)
    {
        GameObject closestDrop = null;
        float closestDistance = Mathf.Infinity;
        Vector3 position = transform.position;

        foreach (GameObject targetDrop in dropOffs)
        {
            Vector3 direction = targetDrop.transform.position - position;
            float distance = direction.sqrMagnitude;
            if(distance < closestDistance)
            {
                closestDistance = distance;
                closestDrop = targetDrop;
            }
        }

        return closestDrop;
    }


    public void RightClick()
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;

        if(Physics.Raycast(ray, out hit, 100))
        {
            if(hit.collider.tag == "Ground")
            {
                agent.destination = hit.point;
                Debug.Log("Moving");
                task = TaskList.Moving;
            }
            else if(hit.collider.tag == "Resource")
            {  
                agent.destination = hit.collider.gameObject.transform.position;
                Debug.Log("Harvesting");
                task = TaskList.Gathering;
                targetNode = hit.collider.gameObject;
            }
        }
    }

    public void OnTriggerEnter(Collider other)
    {
        GameObject hitObject = other.gameObject;

        if(hitObject.tag == "Resource" && task == TaskList.Gathering)
        {
            isGathering = true;
            hitObject.GetComponent<NodeManager>().gatherers++;
            heldResourceType = hitObject.GetComponent<NodeManager>().resourceType;
           
        }
        else if(hitObject.tag == "Drops" && task == TaskList.Delivering)
        {
            if(RM.metal >= RM.maxMetal)
            {
                task = TaskList.Idle;
            }
            else
            {
                RM.metal += heldResource;
                heldResource = 0;
                if (targetNode != null)
                {
                    task = TaskList.Gathering;
                    agent.destination = targetNode.transform.position;
                }
                else task = TaskList.Idle;

            }
        }
    }

    public void OnTriggerExit(Collider other)
    {
        GameObject hitObject = other.gameObject;
       
        if(hitObject.tag == "Resource")
        {
            hitObject.GetComponent<NodeManager>().gatherers--;
            isGathering = false;
        }
    }

    IEnumerator GatherTick()
    {
        while (true)
        {
            yield return new WaitForSeconds(1);
            if(isGathering)
            {
                heldResource++;
            }
        }
    }


}

I apologize afront for the long and painful post, I am trying to do my best learning to code.:smile:

If you don’t have anything selected, then selectInfo.isSelected refers to the property “isSelected” of an object that doesn’t exist, hence the error. All you need to do in this case is check for null before doing that:

            if(hit.collider.tag == "Ground")
            {
                selectedObject = null;
if (selectedInfo != null) {
                selectedInfo.isSelected = false;
                selectedInfo = null;
                Debug.Log("Deselected");
}
            }
1 Like

Thank you so much!
The error no longer happens, but I got something funnier… I can’t reselect the unit. I mean, no errors, no nothing in the console. Got any ideas ?