Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Problems with scripting, Help!

Discussion in 'Scripting' started by HarmlessRaccon, Feb 18, 2020.

  1. HarmlessRaccon

    HarmlessRaccon

    Joined:
    Mar 22, 2018
    Posts:
    7
    Hello everyone!

    I am making a game in which you control a ball that moves up, down, left and right and shoots bullets at incoming enemies. The problem is: I'm trying to not only destroy the enemy object, but also regenerate 1 bullet upon collision with the enemy, but even after trying many ways of detecting the object it always gives me the nullreferenceexception error. The debug successfully informs me that my bullet collided with "Enemy" or "Enemy (Clone)" depending on the occasion, yet after trying gameObject.name, gameObject.tag and compareTag it still does not work. here is my code:


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. public class bulletScript : MonoBehaviour
    5. {
    6.     public Rigidbody2D rb;
    7.     public float moveSpeed = 9;
    8.     Vector2 movement;
    9.     public GameObject bullet;
    10.     playerMovement regen;
    11.     public GameObject Enemy;
    12.     void FixedUpdate()
    13.     {
    14.         movement.x = 1;
    15.         rb.MovePosition(rb.position + movement * moveSpeed * Time.fixedDeltaTime);
    16.         StartCoroutine(destroy());
    17.     }
    18.     void OnCollisionEnter2D(Collision2D collision)
    19.     {
    20.         Debug.Log("Collision with: " + collision.gameObject.name);
    21.         regen = GetComponent<playerMovement>();
    22.         float regenAmmo = regen.bulletAmmo;
    23.         GameObject enemy = GameObject.Find("Enemy");
    24.         GameObject enemy1 = GameObject.Find("Enemy (Clone)");
    25.         if (collision.gameObject == enemy || collision.gameObject == enemy1)
    26.         {
    27.             regenAmmo++;
    28.             Destroy(Enemy);
    29.         }
    30.     }
    31.     IEnumerator destroy()
    32.     {
    33.         yield return new WaitForSeconds(3);
    34.         Destroy(bullet);
    35.     }
    36. }
    Here is the bulletAmmo int im accessing:


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. public class playerMovement : MonoBehaviour
    5. {
    6.     public float moveSpeed = 5f;
    7.     public Rigidbody2D rb;
    8.     Vector2 movement;
    9.     public GameObject Bullet;
    10.     public GameObject Player;
    11.     bool shootNow;
    12.     Vector3 position;
    13.     public float bulletAmmo = 3;
    14.     void Update()
    15.     {
    16.         if (bulletAmmo > 3)
    17.         {
    18.             bulletAmmo--;
    19.         }
    20.         if (bulletAmmo <= 0)
    21.         {
    22.             destroy();
    23.         }
    24.         movement.x = Input.GetAxisRaw("Horizontal");
    25.         movement.y = Input.GetAxisRaw("Vertical");
    26.         float Playerx = Player.transform.position.x;
    27.         float Playery = Player.transform.position.y;
    28.         position = new Vector3(Playerx+1, Playery, 0);
    29.         shootNow = Input.GetKeyDown("q");
    30.         if (shootNow == true)
    31.         {
    32.             Object.Instantiate(Bullet, position, Quaternion.identity);
    33.             bulletAmmo--;
    34.         }
    35.     }
    36.     void FixedUpdate()
    37.     {
    38.         rb.MovePosition(rb.position + movement * moveSpeed * Time.fixedDeltaTime);
    39.     }
    40.     private void destroy()
    41.     {
    42.         Destroy(Player);
    43.     }
    44. }
    The problem is in line 30 in the first script, maybe the program is stopping because it finds the error and doesnt execute the destroy command?

    Anyways, heres a video:
     
  2. unit_dev123

    unit_dev123

    Joined:
    Feb 10, 2020
    Posts:
    989
    This suggest u are trying to access reference that has already been destroy. Check carefully for this.
     
  3. HarmlessRaccon

    HarmlessRaccon

    Joined:
    Mar 22, 2018
    Posts:
    7
    The playerMovement script never gets destroyed until the player dies, parallel to this the bulletAmmo float also never gets destroyed
     
  4. unit_dev123

    unit_dev123

    Joined:
    Feb 10, 2020
    Posts:
    989
    Believe me this is the problem, use debugger to step through and you will find where you destroying first then try to access after :)
     
  5. HarmlessRaccon

    HarmlessRaccon

    Joined:
    Mar 22, 2018
    Posts:
    7
    A
    Alright! I'll check it out, thanks!
     
  6. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,773
    This is actually incorrect. Unity throws a different exception if you're trying to access an object that used to exist but has since been destroyed, and it looks like this:
    Code (csharp):
    1. MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it.
    2. Your script should either check if it is null or you should not destroy the object.
    NullReferenceException and MissingReferenceException are two different things.

    NullReferenceException usually means that you've forgotten to assign a value to whatever you're trying to access.

    @HarmlessRaccon : You video shows an exception, but it's too low resolution and I can't read what line number it's showing. Does that say "28"? That shows the line number where the error occurs.

    If it is line 28, then your problem there is kind of a multi layered problem.
    First of all, you're trying to destroy the object pointed to by the variable Enemy, which as far as I can see is never assigned. So that's why that's null, and causes the exception. You maybe meant to use enemy instead? (lowercase)

    If you fix that though, it still won't work. The broad piece of advice I have to give here is that GameObject.Find is terrible and you should honestly never use it. It's especially wrong for what you're trying to do here. What your code is actually doing there is:
    1) Find two objects, one named "Enemy" and one named "Enemy (Clone)"
    2) compare the collider to those two specific objects
    3) if it matches, destroy a third, unrelated, and probably unassigned object

    Hopefully when I phrase steps one and two like this you can see the problem: There are only two enemies that are capable of being destroyed. GameObject.Find only finds one object, it doesn't return a list of all objects with that name or anything.

    What I think you think you're doing would be more like:
    1) Check to see if the collider's object is named "Enemy" or "Enemy (Clone)"
    2) if it matches, destroy it

    The code for that would look more like:
    Code (csharp):
    1. if (collision.gameObject.name == "Enemy" || collision.gameObject.name == "Enemy (Clone)") {
    2.    Destroy(collision.gameObject);
    3. }
    And I think that will work. It's still not the BEST way to detect this though. For that, I'd probably take advantage of whatever scripts you have on the enemy objects. Let's say that script is called Enemy. Then you can do this:
    Code (csharp):
    1. if (collision.gameObject.GetComponent<Enemy>() != null) {
    2.    Destroy(collision.gameObject);
    3. }
    That way, you're not relying on the names of objects, which is usually a bad idea.
     
  7. unit_dev123

    unit_dev123

    Joined:
    Feb 10, 2020
    Posts:
    989
    use space invader template in learn section.