I need help understanding why this variable returns null.

Hi, so I have a script that controls gameobjects using targets. Lets say I have two gameobjects to be controlled with the mouse, select and move. I have two corresponding targets, one for each gameobject. This script is supposed to allow the user to select a gameobject, find it’s target, and move that target.

Unfortunately the ‘target’ returns null at a certain point, and I cannot figure out why. The process uses tags, and I’ve made sure these are all in order.

Before I dump the script, there are some Debug.Log results to be aware of:

  1. selected is true, because Debug.Log(“Selected”); presents in the console.

  2. the Debug.Log(“found target” + targ.tag) shows in the console, with the correct targ.tag value.

  3. And in SetTarget(), this Debug.Log is present in the console:

    if (target == null)
    Debug.Log(“Obviously something has gone wrong, target is null!”);

Here is the script:

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

public class Movement : MonoBehaviour
{

    //list of the targets to move
    public List<GameObject> targets = new List<GameObject>();

    //list of the gameobjects to be selected
    public List<GameObject> units = new List<GameObject>();

    public bool selected = false;


    public Camera camera;
    private GameObject target;

    void Update()
    {

        target = Select();

        if (selected)
        {
            SetTarget();
        }
    }

    public GameObject Select()
    {
        if (Input.GetMouseButtonDown(0))
        {
            RaycastHit hit = new RaycastHit();
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            if (Physics.Raycast(ray, out hit))
            {
                // The ray hit something. Check all objects in "units" list for a match
                foreach (GameObject unit in units)
                {
                    if (hit.collider.gameObject == unit)
                    {
                        Debug.Log("Selected");
                        selected = true;

                        // Now check for a matching tag on one of the "target" objects
                        foreach (GameObject targ in targets)
                        {
                            // Return the GameObject hit by ray if its tag matches targ's tag.
                            if (hit.collider.gameObject.tag == targ.tag)
                            {
                                Debug.Log("found target" + targ.tag);
                               
                                return targ;
                            }
                        }

                        
                  
                        selected = false;
                    }
                    else
                        selected = false;
                }
            }
        }

        return null;
    }

    void SetTarget()
    {
        
        if (target == null)
            Debug.Log("Obviously something has gone wrong, target is null!");

        if (Input.GetMouseButtonDown(1))
        {
            RaycastHit hit;
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            if (Physics.Raycast(ray, out hit) && target != null)
            {
                target.transform.position = hit.point;
            }
        }
    }
}

So at some point during execution, target becomes null. This occurs on first click of one of the ‘unit’ objects.

Well, you execute your “Select” method every frame in Update. It only returns your target when you press down the mousebutton. The next frame Select is called it will simply return null (line 70 in your code above).

So you should overthink your logic here. Either let the Select method return “target” in line 70, or don’t work with a return value at all and simply set the target inside your Select method.