i have a problem that i dont understand please help

im learning unity and c# via a pathway(this one) and i’ve been thrown into making homing missles with no prior knowledge of projectliles. i was wondering why this error was showing up. i honestly have no idea whatsoever why the error is there.

the problem im having is that everytime i press “f” to spawn a missle for each enemy.
it only spawns 1 missle and the console gives me the following error:

NullReferenceException: Object reference not set to an instance of an object
PlayerController.misslelin () (at Assets/scripts/PlayerController.cs:78)
PlayerController.Update () (at Assets/scripts/PlayerController.cs:31)

this is my player script:

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

public class PlayerController : MonoBehaviour
{
    private Rigidbody PlayerRb;
    public float speed = 5.0f;
    public float PowerUpStrenght = 15.0f;
    private GameObject FocalPoint;
    public bool HasPowerup = false;
    public bool hasmissle = false;
    public GameObject PowerUpIndicator;
    public GameObject misslewarner;
    public spauwnar spawner;
    public GameObject missle;
    public GameObject tmpmislle;
    public RocketBehavior rocketBehavior;

    void Start()
    {
        FocalPoint = GameObject.Find("focal point");
        PlayerRb = GetComponent<Rigidbody>();
    }

  
    void Update()
    {
        if (hasmissle == true && Input.GetKeyDown(KeyCode.F))
        {
            misslelin();
        }
        float ForwardInput = Input.GetAxis("Vertical");

        PlayerRb.AddForce(FocalPoint.transform.forward * ForwardInput * speed);

        PowerUpIndicator.transform.position = transform.position + new Vector3(0, -0.5f, 0);
        misslewarner.transform.position = transform.position + new Vector3(0, -0.5f, 0);
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("powerup"))
        {
            HasPowerup = true;
            PowerUpIndicator.gameObject.SetActive(true);
            StartCoroutine(PowerUpCountdownRoutine());
            Destroy(other.gameObject);

        }
        if (other.CompareTag("missle"))
        {
            hasmissle = true;
            misslewarner.gameObject.SetActive(true);
            Destroy(other.gameObject);
            StartCoroutine(PowerUpCountdownRoutine2());
        }
    }
    IEnumerator PowerUpCountdownRoutine2()
    {
        yield return new WaitForSeconds(7);
        hasmissle = false;
        misslewarner.gameObject.SetActive(false);
    }

    IEnumerator PowerUpCountdownRoutine()
    {
        yield return new WaitForSeconds(7);
        HasPowerup = false;
        PowerUpIndicator.gameObject.SetActive(false);
    }

    void misslelin()
    {
        foreach (var enemy in FindObjectsOfType<Enemy>())
        {
            tmpmislle = Instantiate(missle, transform.position + Vector3.up, Quaternion.identity);
            rocketBehavior.Fire(enemy.transform);



        }
    }



    private void OnCollisionEnter(Collision collision)
    {
        if(collision.gameObject.CompareTag("Enemy") && HasPowerup)
        {
            Rigidbody EnemyRigid = collision.gameObject.GetComponent<Rigidbody>();
            Vector3 awayfromplayer = collision.gameObject.transform.position - transform.position;
            EnemyRigid.AddForce(awayfromplayer * PowerUpStrenght, ForceMode.Impulse);
        }
    }

}

and this is my missle script:

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

public class RocketBehavior : MonoBehaviour
{
    private Transform target;
    private float speed = 15.0f;
    private bool homing;
    private float rocketStrength = 15.0f;
    private float aliveTimer = 5.0f;
 
    void Update()
    {
        if (homing && target != null)
        {
            Vector3 moveDirection = (target.transform.position -
            transform.position).normalized;
            transform.position += moveDirection * speed * Time.deltaTime;
            transform.LookAt(target);
        }
    }
    void OnCollisionEnter(Collision col)
    {
        if (target != null)
        {
            if (col.gameObject.CompareTag(target.tag))
            {
                Rigidbody targetRigidbody = col.gameObject.GetComponent<Rigidbody>();
                Vector3 away = col.transform.position - transform.position;
                away.y = 0;
                targetRigidbody.AddForce(away.normalized * rocketStrength, ForceMode.Impulse);
                Destroy(gameObject);
            }
        }
    }
    public void Fire(Transform homingTarget)
    {
        target = homingTarget;
        homing = true;
        Destroy(this.gameObject, aliveTimer);
    }

}

this is my player object:

and this is my missle prefab:

We have a sticky about NullreferenceExceptions .

It basically tells you that you are accessing an object reference which is empty. It also tells you where.
At line 31 you call misslelin(), and at line 78 inside that function you write:

rocketBehavior.Fire(enemy.transform);

That line contains two object references: ‘rocketBehavior’ and ‘enemy’. One of them is null. Since the loop is executed for each enemy found by FindObjectsOfType, enemy wont be null. Thus ‘rocketBehavior’ is not actually set to anything.
(If it was less obvious, you could use Debug.Log() to print your references there and see which is null)

And if you check your screenshots, “Rocket Behavior” is set to None in the inspector of your player object. Depending on your setup you either forgot to drag it into there, or wanted to dynamically use the rocket behavior script found on the rocket you instantiate in line 77, which would make sense to me. This also means you dont need the public rocketBehavior reference in your player script at all.

So, presumably, you want something like:

// Take with a grain of salt, i didnt code in C# in ages

tmpmislle = Instantiate(missle, transform.position + Vector3.up, Quaternion.identity);
RocketBehavior rb = tmpmislle.GetComponent<Rocketbehavior>();
rb.Fire(enemy.transform);

Just like with rocketBehavior, you also dont need your player to store a reference to tmpmislle. Also please settle on one way to misspell ‘missile’, it’s hard to memorize the correct typo :stuck_out_tongue:

2 Likes

thanks!!!
it worked
thats a lot of help.
and sorry for the bad variables i didnt expect anybody else to need to see this code:sweat_smile:

In a nutshell, there are essentially two types of data in C#.
One of them is considered as “primitive”, and the other needs some special catering and so is considered “more complex”. There are technical and pragmatical reasons for this, but I’m keeping it simple.

Primitive data is for example, an integer, or a character (like a letter), or true/false.
Objects and arrays of primitives are not primitives themselves, they are of the other kind.
Text data is something in between, but mostly it’s not primitive either.

Variables can be declared to hold any of the two, as you see fit.

C# on its own doesn’t like when you attempt to use uninitialized variables, that is, variables that haven’t been explicitly assigned some value. But because this is in Unity, Unity likes to deserialize some values, and so some things might be initialized even if you didn’t do it yourself.

Unlike primitive data, objects etc. have this special value null. This is because ‘they don’t refer to anything’ in particular. Or ‘they refer to null’ which is like a limbo assignment. Almost like a placeholder in place of something real. And it’s quite safe to keep them that way, until you decide to act upon them. When you try to call some method or piece of data on an object variable that was set to null, your program will crash because there is nothing actually there.

Primitive data doesn’t work this way, has no null, but also contains nothing to be called. For number types usually a zero is the default, as an example.

We all encounter null errors, all the time, and that’s usually an indicator that we forgot to assign something of value. Which is actually neat and lets you catch errors early, unless you make it complicated for yourself, then it’s not neat. You can also explicitly test whether something is set to null, because you might sometimes want to use this placeholder to track some special use case or detect a particular behavior or defect.

Perhaps one part of your code asks for an enemy, and a different one does the assigning, in which case you might want to check null on receiving. That’s because you’ve deliberately decided to interpret null as a signal that ‘no enemy was found’.

All in all, prepare for much more nulls. After having hunted 10 000 nulls you’ll be a battle-hardened veteran.