can't get rid of destroyed object reference

trickCube go is a cube that is located way off the screen, just as a utility used to hold the originalColor and also serves as a temporary target.
When player approaches and faces the cube gameObject, it turns gray, as it’s marked to be destroyed when fire is pressed. When the player doesn’t press fire and just walks away from the cube, it should turn to it’s original color. When I press fire and destroy a cube, all seems fine, but when I approach another cube, I suddenly get this error:

MissingReferenceException: The object
of type ‘GameObject’ has been
destroyed but you are still trying to
access it. Your script should either
check if it is null or you should not
destroy the object.
DmgCube_scr.MarkTarget () (at Assets/__scripts/DmgCube_scr.cs:48)
DmgCube_scr.Update () (at Assets/__scripts/DmgCube_scr.cs:38)

I know what that means, so please don’t bother explaining, just point out to me what am I missing in my code, where did I make the mistake.

using UnityEngine;
using System.Collections;

public class DmgCube_scr : MonoBehaviour {
	
	Color originalColor;
	GameObject target;
	GameObject lastTarget;
	GameController_scr gc_scr;
	GameObject trickCube;

	void Awake()
	{
		gc_scr = GameObject.Find ("GameController").GetComponent<GameController_scr>();
		trickCube = GameObject.Find ("trickCube");
	}
	
	void Start () {
		originalColor = trickCube.renderer.material.color;
		lastTarget = trickCube;
	}
	

	void Update () {

		// ::::::::::::::::::::::::::::::::::::::::::::::: TARGETING :::::::::::::::::::::::::::::::::::::::::::
		Ray targetingRay = new Ray(transform.position, transform.TransformDirection (Vector3.forward));
		RaycastHit targetHit;
		
		if(Physics.Raycast (targetingRay, out targetHit, 1f))
		{
			if(targetHit.transform.gameObject.tag == "cube")
			{
				target = targetHit.transform.gameObject;
				Debug.Log ("target = " + target.name);
				//Debug.Log ("last target = " + lastTarget.name);

				MarkTarget ();
			}
		}

	}

	void MarkTarget()
	{
		if(target != lastTarget)
		{
			lastTarget.renderer.material.color = originalColor;
			target.renderer.material.color = Color.gray;
			lastTarget = target;
		}

	}
	
	// ::::::::::::::::::::::::::::::::::::::::::::::: ATTACKING :::::::::::::::::::::::::::::::::::::::::::
	public void Attack()
	{
		if(gc_scr.dmgCharged)
		{
			Destroy (target);
			gc_scr.dmgCharged = false;
			lastTarget = trickCube;
		}
	}
}

the error happens in which line

hi 7672 - I updated the error message.

3 Answers

3

Is the Attack() function called before MarkTarget() ?

If target is destroyed, that could mean that target != lastTarget is true, always. So when it goes inside, it tries to assign lastTarget = target, which is a destroyed object.

You could modify MarkTarget() this way:

  void MarkTarget()
     {
         if(target != null && target != lastTarget)
         {
             lastTarget.renderer.material.color = originalColor;
             target.renderer.material.color = Color.gray;
             lastTarget = target;
         }
 
     }

when you destroy your object your lastTarget will be null so you have to check for it

if(( target != lastTarget) && (lastTarget!=null) )

this removes the error, but it also removes the scripts functionality which is the reason I created this script in the first place. I did what you suggested and then whatever cube gameObject my player faces, the script doesn't mark it as an object to be destroyed.

i think we got a misunderstanding here we put our target to lastTarget hen we want to change it color to its original color later but when its destroyed why you need lastTarget to change its color to its original its Destroyed there is nothing there to change its color

I tried to use the line of code you provided above, but it didn't work. I think I've got it though...just need a few more minutes.

THIS is the way it works like it should:

using UnityEngine;
using System.Collections;

public class DmgCube_scr : MonoBehaviour {
	
	Color originalColor;
	GameObject target;
	GameObject lastTarget;
	GameController_scr gc_scr;
	GameObject trickCube;


	void Awake()
	{
		gc_scr = GameObject.Find ("GameController").GetComponent<GameController_scr>();
		trickCube = GameObject.Find ("trickCube");

	}
	
	void Start () {
		originalColor = trickCube.renderer.material.color;
		lastTarget = trickCube;
	}
	

	void Update () {

		// ::::::::::::::::::::::::::::::::::::::::::::::: TARGETING :::::::::::::::::::::::::::::::::::::::::::
		Ray targetingRay = new Ray(transform.position, transform.TransformDirection (Vector3.forward));
		RaycastHit targetHit;
		
		if(Physics.Raycast (targetingRay, out targetHit, 1f))
		{
			if(targetHit.transform.gameObject.tag == "cube")
			{
				target = targetHit.transform.gameObject;
				Debug.Log ("target name = " + target.name);
				MarkTarget ();
				lastTarget = target;
			}
		}

	}

	void MarkTarget()
	{
		if(target != lastTarget)
		{
			target.renderer.material.color = Color.gray;

			if(lastTarget != null)
			{
				lastTarget.renderer.material.color = originalColor;
			}
		}
	}
	
	// ::::::::::::::::::::::::::::::::::::::::::::::: ATTACKING :::::::::::::::::::::::::::::::::::::::::::
	public void Attack()
	{
		if(gc_scr.dmgCharged)
		{
			Destroy (target);
			lastTarget = trickCube;
			gc_scr.dmgCharged = false;

		}
	}
}