Null Ref error in shooter script due to removal of attacker in certain lane

This is similar to what’s posted before in:

Yes, so the problem is that there ought to be an attacker in that lane or program will scream error. My coding in C# is still not good… so what can I do to resolve the error? I do like Rick’s idea of halting the stream of attackers in certain lanes in the earlier levels. How can I achieve that without errors?

PS. I had my cactus shoot 2 projectiles instead of 1, hence the two firing methods. There’s possibly a neater way of having 2 projectiles, but I don’t know how to achieve that at the moment. This is just a quick way.

This is my shooter script:

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

public class Shooter : MonoBehaviour
{
[SerializeField] GameObject projectileC, gunC, projectileZ, gunZ; // can add a few variables
AttackerSpawner myLaneSpawner;
Animator animator;
GameObject projectileParent;
const string PROJECTTILE_PARENT_NAME = “Projectiles”;

private void Start()
{
    SetLandSpawner();
    animator = GetComponent<Animator>();
    CreateProjectileParent();
}

private void CreateProjectileParent()
{
    projectileParent = GameObject.Find(PROJECTTILE_PARENT_NAME);
    if (!projectileParent)
    {
        projectileParent = new GameObject(PROJECTTILE_PARENT_NAME);
    }
}

private void Update()
{
    
    if (IsAttackerInLane())
    {
        // change animation state to shooting
        animator.SetBool("isAttacking", true);
    }
    else
    {
        // change animation state to idle
        animator.SetBool("isAttacking", false);
    } 
}

private void SetLandSpawner()
{
    AttackerSpawner[] spawners = FindObjectsOfType<AttackerSpawner>();   // creating the array

    foreach (AttackerSpawner spawner in spawners)
    {
        // check if spawner (of Attacker) is in the same position as our defender's current position
        bool IsCloseEnough = 
            (Mathf.Abs(spawner.transform.position.y - transform.position.y) 
            <= Mathf.Epsilon);
        if (IsCloseEnough)
        {
            myLaneSpawner = spawner;
        }
    }
}

private bool IsAttackerInLane()
{
    // if my lane spawner child count is less than or equal to 0, then return false
    // i.e. to check if there's an attacker in our defender's lane
    if (myLaneSpawner.transform.childCount <= 0)
    {
        return false;
    }
    else
    {
        return true;
    }
}
public void FireC()       // Firing CactusFlower
{
    GameObject newProjectile =  
        Instantiate(projectileC, gunC.transform.position, transform.rotation)
        as GameObject;
    newProjectile.transform.parent = projectileParent.transform;
}

public void FireZ()    // Firing Zuchinni 
{
    GameObject newProjectile = 
        Instantiate(projectileZ, gunZ.transform.position, transform.rotation)
        as GameObject;
    newProjectile.transform.parent = projectileParent.transform;
}

}

Hi Andes,

First of all, you are right: There is a more elegant way to fire two projectiles. Look up method overloading for C#. This will help you refactor your code. Having two methods with basically the same code is not an error, though, so your code is fine regarding the result.

Secondly, NullReferenceException means that a reference (“link”) to an instance is missing. Double click on the error message to see to which line in your code it is referring. Add Debug.Logs to find the root of the problem.


See also:

For the null reference error, it’s this part:
private bool IsAttackerInLane()

{
    // if my lane spawner child count is less than or equal to 0, then return false
    // i.e. to check if there's an attacker in our defender's lane

    if (myLaneSpawner.transform.childCount <= 0)
    {
        return false;
    }
    else
    {
        return true;
    }
}

How do I write
if the myLaneSpawner.transform.childCount <= 0
or if myLaneSpawner.transform.childCount is null
I want it to return false?

If I add the null checks in front, it works.

private bool IsAttackerInLane()
{
if (myLaneSpawner is null)
{
return false;
}

    if (myLaneSpawner.transform.childCount <= 0)
    {
        return false;
    }
    else
    {
        return true;
    }
}

BUT if I try to add the null check as an OR condition in the childCount line, then the null reference return again. Why?

    if (myLaneSpawner.transform.childCount <= 0 || myLaneSpawner is null)
    {
        return false;
    }
    else
    {
        return true;
    }

If you’re still having the null error, odds on, it’s myLaneSpawner that’s coming up with your null.

To see if this is the case try this:

{
    // if my lane spawner child count is less than or equal to 0, then return false
    // i.e. to check if there's an attacker in our defender's lane

if (myLaneSpawner == null)
{
Debug.Log("It's null");
return false;
}

    if (myLaneSpawner.transform.childCount <= 0)
    {
        return false;
    }
    else
    {
        return true;
    }
}

hmm. I gotta figure out this code formatting again ;(

You beat me to the post by a minute.

I think this will still give a null error. If you switch the order I’m pretty sure with OR checks, if true, it’ll skip checking the second test.

Yes, its the MyLaneSpawner that is null when Rick turns certain lanes off for level progression.

Interestingly, if I reverse the order of the conditions as in

    if (myLaneSpawner is null || myLaneSpawner.transform.childCount <= 0)
    {
        return false;
    }
    else
    {
        return true;
    }

Then it works. Cos I think having the check as a standalone makes for more lengthy codes.

I always go for more readable code, over length of code. Not to say I don’t prefer shorter methods. Trust me, I do.

Yes, the check as a stand alone does make it for more lengthy code but I put it in there to show you that it was myLaneSpawner causing your null error issues (which I believe you’ll still need to solve).

Having both in the conditionals in the if statement is fine in a lot of cases… if all you’re trying to do is remove the error, but in doing so, you’ve eliminated your error and introduced a logic error which will mean, you don’t know that an object doesn’t exist where it (probably - I’m assuming) should. Basically meaning, if you should have a myLaneSpawner, this code is only kicking the can (the problem) down the road. Much like taking an almost flat battery out of a smoke detector. It doesn’t fix the problem, it just stops the warning from showing.

Does that make sense?

MyLaneSpawner is null because Rick’s suggestion to toggle off certain lanes of attackers in the easier levels (there were originally 5 lanes of attackers).

But yes, I do get your point that having the null check as a standalone is clearer, especially for a beginner. But in trying to lump the two condition checks together I learnt that sequence of checks is important and that || is the logical OR in the conditional checks.

1 Like

How are you getting on with this, @Andes?


See also:

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms