0

I have Enemy script that gets another Game Object, as target if it collides with it, in the Start() Method. The other Game Object is being Instantiated with a button and is not Active in the scene from the start. So when the Enemy spawns it tries to search for that Object but when it's not active it throws Null Reference Exceptions Error. My question is how can I check if that object is null or how to stop the error in other ways? Enemy script:

private Transform newtarget;
void Start()
{
    newtarget = GameObject.FindGameObjectWithTag("heroK").GetComponent<Transform>();
}
derHugo
  • 83,094
  • 9
  • 75
  • 115

2 Answers2

0

Checking for NULL is straight forward, tho it probably won't help you much with this problem.

if(newTarget == null){
}

You can also work with try on a code section that is likely to fail

try{
  newtarget = GameObject.FindGameObjectWithTag("heroK").GetComponent<Transform>();
}

In this case it might be better to go about this the other way around. Have the instantiated object find all enemies and reference itself to them.

/*In start method of your spawned object script*/
Enemy scripts[]=FindObjectsOfType(typeof(Enemy));
foreach(Enemy script in scripts){
  script.SetNextTarget(this.transform);
}

/*New method in your Enemy script*/
void SetNextTarget(Transform target){
  nextTarget = target;
}
Voidsay
  • 1,462
  • 2
  • 3
  • 15
0

About checking for null, there are multiple ways to express it, though they do pretty much the same:

if (GameObject.FindGameObjectWithTag("heroK") != null)
    {
        newtarget = GameObject.FindGameObjectWithTag("heroK").GetComponent<Transform>();
    }

    if (!GameObject.FindGameObjectWithTag("heroK"))
    {
        newtarget = GameObject.FindGameObjectWithTag("heroK").GetComponent<Transform>();
    }

    newtarget = GameObject.FindGameObjectWithTag("heroK")?.GetComponent<Transform>();

Be careful with setting variable first, and checking for null later, as it won't really help you:

newtarget = GameObject.FindGameObjectWithTag("heroK").GetComponent<Transform>();

// runtime will exit your method prematurely here, as you are trying to call GetComponent on a null

if (newtarget != null) {}

This could help with inactive game objects which is using FindObjectsOfType<T>(true)

But checking for null during start is one thing. You still need to set your target, so you would have to do that periodically, or when the new object is instantiated, which I don't think is really convenient.

I personally would pool (instantiate, and set inactive for future use) all the objects that you are now instantiating during runtime. This way, you could have all objects created beforehand and then set references during their initialization by passing them a list of enemies, or passing them an object that manages the enemies, if the list would be changing a lot.

bartol44
  • 562
  • 2
  • 12
  • Using the `FindObjectWithTag` repeatedly is a waste of resources, you would rather cache the result in a variable. `transform` is a property and better to use that than `GetComponent` .. and **never** use `?.` or `??` on anything derived from `UnityEngine.Object` as it bypasses the custom implementation for `==` they have and rather works on a `System.Object` basis which might behave unexpectedly – derHugo Sep 07 '22 at 16:08
  • I was just demonstrating, but true that should be cached. I have no idea how I missed GetComponent when copying from OPs code. Didn't know though about not using ?. or ?? with unity objects, thanks! – bartol44 Sep 07 '22 at 18:14
  • see e.g. https://stackoverflow.com/a/62678296/7111561 for more detail about the null propagation issue ;) – derHugo Sep 08 '22 at 07:59