-2

This suddenly stopped working, when trying to instantiate the projectile is tells me the projectile is null. Even though i declare a value to it. The Debug tells me Start() is run. Can't give much more context.

The question here is not "what does this error mean" it's "why is it null?" I got a great reply from Daedalus who told me to stay away from string lookups. I will try that and tell y'all if that worked.

EDIT:// My teacher added some code in the text that i forgot to remove (he couldn't find out why i was getting null) it is however removed now and this is the correct code that does not work. The tag is not miss-spelled, I have checked the casing etc.

void Start()
{
    targPlayer = GameObject.FindGameObjectWithTag("Player").transform;
    projectile = GameObject.Find("Projectile");
    Debug.Log("was run");
}

void Update()
{
    fire -= Time.deltaTime;
    dmg -= Time.deltaTime;

    if (fire <= 0)
    {
        if (Vector2.Distance(transform.position, targPlayer.position) <= detectionRange)
        {
            // This is where the error happens
            Instantiate(projectile, transform.position, Quaternion.identity);
        }
        fire = fireRate;
    }

    if (Vector2.Distance(targPlayer.position, transform.position) <= detectionRange && Vector2.Distance(targPlayer.position, transform.position) >= stopRange)
    {
        transform.position = Vector2.MoveTowards(transform.position, targPlayer.position, movSpeed * Time.deltaTime);
    }
}
Adam
  • 1
  • 3
  • Which line throws the exception? – mjwills May 08 '18 at 10:34
  • 3
    Possible duplicate of [What is a NullReferenceException, and how do I fix it?](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – CodeNotFound May 08 '18 at 10:34
  • 1
    I'm going to assume that `GameObject.FindGameObjectWithTag("Projectile");` returns null (when you reassign projectile in Update()). – ProgrammingLlama May 08 '18 at 10:34
  • targPlayer = GameObject.FindGameObjectWithTag("Player").transform; is it there GameObject.FindGameObjectWithTag("Player") ?? – Chopi May 08 '18 at 10:36
  • Projectile is uppercase in `Update()` and lowercase in `Start()`? – Gert Kommer May 08 '18 at 14:53
  • **1.** I know what NullReferenceException means, what i don't know is why I get it since the spelling of the tag is correct and I assign a value to GameObject projectile; in Start(). **2.** The line that previously was in Update() is irrelevant. I get the same error without it (i updated the code in the original post) – Adam May 08 '18 at 20:12

1 Answers1

1

There are many possible solutions here, so I'll go through a handful which come to mind.

First off, lookups with strings are one thing I imagine most developers would call objectively bad. Putting case and culture issues for comparison aside, it's incredibly easy to make a typo, for you or another team member to later change the name of that object without remembering that these lookups are reliant on it, and when used in non-trivial cases, there are serious performance concerns. This is especially true of Unity, which will simply iterate through the hierarchy until it finds a matching object, for essentially all of the find calls.

Something like the above must have happened if your instantiate call is failing.

You will likely want to look into object pooling at some point, but let's proceed with the instantiation calls.

To get around the string lookups, you can make the projectile a variable.

public Transform projectile;

This will allow you to assign it in the inspector. It's likely that no other scripts should be allowed to access this variable, so for bonus points, you can use the SerializeField attribute to serialise a private variable, and assign it in the inspector.

[SerializeField] private Transform projectile;

You will then have immediate access to the projectile without any lookup overhead, and without the worry of breaking the lookups.

Your design philosophy will surely change a lot as you progress, and I'd argue that you shouldn't be tying any of this sort of data to logical classes (just in case anybody mentions this), but I'd say it's a good step in the right direction to begin by changing your lookup structure.

Daedalus
  • 86
  • 10
  • Okay sounds good. I will try to assign it in the inspector when i get home. It feels odd to assign in the inspector and therefore I've avoided it. Never had a reason to do it that way before. I'll get back to you sometime tomorrow after I've tried this. – Adam May 08 '18 at 20:16
  • Honestly it is odd to assign things in the inspector in most cases, but it's the middle ground between having references floating around in the scene and having a set data structure. You could think of it as, with the Find lookups, you're using the scene as a database. Moving to the inspector, you have a far more reliable database structure, but it still isn't as clean as a dedicated database for most cases (though it definitely works). And then you have the final step of using some actual database to pipe in your asset data to logical classes which can work with it. – Daedalus May 09 '18 at 00:09
  • Fair enough. It worked when I assigned the prefab in the inspector. But if you don't mind me asking a short question here. I have a player with an arm. They are seperate prefabs and i want the arm to follow the player with transform.parent or SetParent. Although i only got them to work with string-lookup. Any idea why? – Adam May 09 '18 at 06:53