Search Unity

Code works, but I get hammered with error messages

Discussion in 'Scripting' started by Adjaar7, Jan 11, 2021.

  1. Adjaar7

    Adjaar7

    Joined:
    Jan 6, 2020
    Posts:
    22
    I have a simple powerup script that is attached to a prefab of a powerup. Once a player runs over the powerup, it sends its name to a powermanager script that handles the UI and what it does. The scripts work fine, but I'll get 3 big "Object reference not sent to an instance of an object" every time I hit a powerup.

    Here's the code
    Code (CSharp):
    1.  
    2. public class Powerups : MonoBehaviour
    3. {
    4.     string power;
    5.     GameObject player;
    6.  
    7.     private void Start()
    8.     {
    9.         power = this.gameObject.name;
    10.     }
    11.  
    12.     private void OnTriggerEnter2D(Collider2D collision)
    13.     {
    14.         switch (collision.name)
    15.         {
    16.             case "Player1":
    17.                 player = GameObject.Find("HUD P1/Powerups/Power");            
    18.                 break;
    19.             case "Player2":
    20.                 player = GameObject.Find("HUD P2/Powerups/Power");
    21.                 break;
    22.             default:
    23.                 break;
    24.         }
    25.         player.GetComponent<PowerManager>().currentPower(power);
    26.  
    27.         Destroy(gameObject);
    28.     }
    29. }
    and the error points out line 25, which is player.GetComponent<PowerManager>().currentPower(power);
    I am hoping to avoid making player public on each HUD and dragging it from the inspector because I have done it so often in the past and I want to write more self reliant code. One time I messed things up royally when I cancelled mid build and unity made me add every reference back in the inspector and it wasted a ton of time.

    I'm just confused that player has a null reference, when I tell them a few lines ago what I want player to be.
    Thanks for any help, it's really just annoying and I currently have no performance issues.
     
  2. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,187
    If it's line 25, then either player is null, or getting the component is returning null.

    GameObject.Find is bad to use anyways. Instead of doing that or dragging and dropping, you should have a single manager/singleton object that is connected to your HUD power gameobjects. Then you can reference these objects through that single object.

    Many times you might see this in code like

    PowerManager.Instance.hudp1;
    PowerManager.Instance.hudp2;

    Just as an example. This is a pretty common system because you may run into several situations where you can't drag and drop (like spawning in bullets, or enemies).

    However, that being said, your issue is you aren't always telling the code what player is. As you can see, your switch statement has a default condition where player could have no value. With this being the case, you should check if player is null, and if it is, do nothing. Note that you should add a Debug.Log statement to print out the value of collision.name before your switch statement and that will help you to debug why default might trigger sometimes.
     
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,694
    The answer is always the same... ALWAYS. It is the single most common error ever. Don't waste your life on this problem. Instead, learn how to fix it fast... it's EASY!!

    Some notes on how to fix a NullReferenceException error in Unity3D
    - also known as: Unassigned Reference Exception
    - also known as: Missing Reference Exception

    http://plbm.com/?p=221

    The basic steps outlined above are:
    - Identify what is null
    - Identify why it is null
    - Fix that.

    Expect to see this error a LOT. It's easily the most common thing to do when working. Learn how to fix it rapidly. It's easy. See the above link for more tips.

    This is the kind of mindset and thinking process you need to bring to this problem:

    https://forum.unity.com/threads/why-do-my-music-ignore-the-sliders.993849/#post-6453695

    Step by step, break it down, find the problem.
     
    Brathnann likes this.
  4. Adjaar7

    Adjaar7

    Joined:
    Jan 6, 2020
    Posts:
    22
    I wish I knew the single manager thing before. This project is nearing complete but I will definitely do this next time! Having double things for each player has been an absolute nightmare
     
  5. Adjaar7

    Adjaar7

    Joined:
    Jan 6, 2020
    Posts:
    22

    very valid and I do get the error a lot. I usually can find out what is null and fix that, however I didn't understand how to fix it because I thought I didn't make it null through my script already
     
  6. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    691
    You can streamline this considerably, there are some redundant and unnecessary parts. For example, you can just use "name", this is the same as this.name, gameObject.name, or this.gameObject.name. You don't need to hold that in the variable power either, it's accessible anywhere. Also you don't need the player GameObject at all if you just call the method in one line. This will eliminate the errors that you were getting by having a default fallback.

    Note that although using the variable name "collision" for a Collider2D is technically fine (you can call it anything), there is a difference between Colliders and Collisions, and I'd recommend your variable names match for clarity (I changed it below). OnTrigger events return Colliders, OnCollision events return Collisions, and the two types have similar but also different properties and methods.

    I haven't set up all the parts to test it fully, but it should work ;)


    Code (CSharp):
    1. public class Powerups : MonoBehaviour
    2. {
    3.     private void OnTriggerEnter2D(Collider2D collider)
    4.     {
    5.         switch (collider.name)
    6.         {
    7.             case "Player1":
    8.                 GameObject.Find("HUD P1/Powerups/Power").GetComponent<PowerManager>().currentPower(name);
    9.                 Destroy(gameObject);
    10.                 break;
    11.             case "Player2":
    12.                 GameObject.Find("HUD P2/Powerups/Power").GetComponent<PowerManager>().currentPower(name);
    13.                 Destroy(gameObject);
    14.                 break;
    15.         }
    16.         // Probably don't want Destroy out here, otherwise any other Trigger colliding will destroy it
    17.     }
    18.  
    19. }
     
  7. Adjaar7

    Adjaar7

    Joined:
    Jan 6, 2020
    Posts:
    22

    Thanks! I always want to streamline my code and I find that whenever I get a solution I'm too exhausted by it to see if I can do it better. I really appreciate this sort of response
     
    seejayjames likes this.