Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Referencing player positions after Instantiating = Object reference not set error

Discussion in 'Scripting' started by Shramper, Jul 12, 2016.

  1. Shramper

    Shramper

    Joined:
    Jun 1, 2013
    Posts:
    5
    Hi guys!

    I'm new here, so if this issue isn't in the right thread, please let me know!

    I'm getting a System.NullReferenceException error in my Player script, "Object reference not set to an instance of an object". I understand this essentially means something doesn't exist, yet I can't for the life of me figure it out. I'm starting to think it has to do with the order or time it takes to Instantiate the GameObjects into play from the Main script, but I can't think of any solutions.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Player : MonoBehaviour {
    5.  
    6.     public float maxSpeed = 10;
    7.     public float speed = 50f;
    8.     public float jumpForce = 150f;
    9.  
    10.     public Vector2 targetPosition;
    11.  
    12.     public bool DIVE;
    13.     public bool BUCK;
    14.  
    15.     public bool isGrounded;
    16.  
    17.     private Rigidbody2D playerRB2D;
    18.     private Animator anim;
    19.  
    20.     public GameObject player2;
    21.  
    22.  
    23.     // Use this for initialization
    24.     void Start () {
    25.    
    26.         playerRB2D = gameObject.GetComponent<Rigidbody2D> ();
    27.         anim = gameObject.GetComponent<Animator> ();
    28.  
    29.         player2 = GameObject.Find ("Player2");
    30.  
    31.     }
    32.    
    33.     // Update is called once per frame
    34.     void Update () {
    35.  
    36.         targetPosition = player2.transform.position;
    37.  
    Right up the line 36 I get the error. The code is pretty long, so I wouldn't want to spam this thread, but if I have to, please let me know. Debugging gives me a "The name 'this' does not exist in the current context" and I don't understand why it's referring "this" at all!

    Here's the script which everything gets put into play:
    Code (CSharp):
    1. public class Main : MonoBehaviour {
    2.  
    3.     public GameObject player1Prefab;
    4.     public GameObject player2Prefab;
    5.     public GameObject groundPrefab;
    6.  
    7.     public Vector2 player1Spawn;
    8.     public Vector2 player2Spawn;
    9.     public Vector2 groundPos;
    10.  
    11.     // Use this for initialization
    12.     void Start () {
    13.  
    14.         player1Spawn = new Vector2(2, 5);
    15.         player1Spawn = new Vector2(4, 5);
    16.         groundPos = new Vector2 (-7, -2);
    17.  
    18.  
    19.         GameObject Player1 = Instantiate (player1Prefab) as GameObject;
    20.         GameObject Player2 = Instantiate (player2Prefab) as GameObject;
    21.         GameObject Ground = Instantiate (groundPrefab) as GameObject;
    22.  
    23.         Player1.transform.position = player1Spawn;
    24.         Player2.transform.position = player2Spawn;
    25.         Ground.transform.position = groundPos;
    26.  
    27.     }
    28.    
    29.     // Update is called once per frame
    30.     void Update () {
    31.  
    32.     }
    33. }
    It works out well enough until I add the players. I'm pretty certain because both players in their scripts require each other's coordinates, that when they spawn, their positions can't be immediately figured out for whatever reason. It's driving me bonkers, and I can't think of anything concerning my level of programmer (I'm mostly an artist). If anyone can help this Unity noob, I'd be really appreciative!

    Thanks in Advance!
     
  2. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    Can you please post the full error code from the Unity console? From the code you posted it appears your "player2" reference is null.

    Also, why don't you just inject the player opponents when instantiating instead of using GameObject.Find? Change your Player script so "player2" is called "Opponent" to help keep naming clearer..
    Code (csharp):
    1. public GameObject player2;
    to
    Code (csharp):
    1. public GameObject Opponent;
    Then update your Main script to something like this.. *Note* I assume both players have the Player script.
    Code (csharp):
    1. GameObject player1Obj = Instantiate(player1Prefab) as GameObject;
    2. Player player1 = player1Obj.GetComponent<Player>();
    3.  
    4. GameObject player2Obj = Instantiate(player2Prefab) as GameObject;
    5. Player player2 = player2Obj.GetComponent<Player>();
    6.  
    7. player1.Opponent = player2Obj;//inject reference
    8. player2.Opponent = player1Obj;//inject reference
     
    Last edited: Jul 13, 2016
  3. Shramper

    Shramper

    Joined:
    Jun 1, 2013
    Posts:
    5
    I'm sorry, I didn't provide enough context as to what I'm trying to create, and it's probably causing some confusion.

    This is a 2 player game, which is why I have player 1's and 2's. I originally had it as player 1 only, and would signify player 2 as simply 'target' and would have target as a simple gameobject the player could track and collide with. The idea is that the players need to know where the each other are for them to attack. The problem seems to originate to where the variable for their positions are, and from your guess of one of the game objects begin null, I'm pretty sure it's an instantiation problem and causes a error, even when both players spawn at the same time.

    Here's the error code:
    Code (CSharp):
    1. NullReferenceException: Object reference not set to an instance of an object
    2. Player.Update () (at Assets/Player.cs:36)
    I know the problem. But I don't know how I'd be able to spawn the characters without their position info being relayed to each other. Otherwise there's an instant error based on who spawned first.
     
  4. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    Line 36 of your "Player" script is throwing the exception. This means that either "player2" is null or "player2.transform" is null(which would be a special case). You should no longer get the exception if you inject a valid "player2" reference immediately after instantiation which is what I suggested in my first reply...

    Please post the console message results of the following code additions in your "Main" script.
    Code (csharp):
    1. GameObject Player1 = Instantiate(player1Prefab) as GameObject;
    2. Debug.Log("Player1 is " + ((Player1 == null) ? "null" : "not null"));//add this
    3. GameObject Player2 = Instantiate(player2Prefab) as GameObject;
    4. Debug.Log("Player2 is " + ((Player2 == null) ? "null" : "not null"));//add this
     
  5. Shramper

    Shramper

    Joined:
    Jun 1, 2013
    Posts:
    5
    Got some errors, hopefully they answer some questions.

    Code (CSharp):
    1. Assets/Main.cs(23,45): error CS0119: Expression denotes a `type', where a `variable', `value' or `method group' was expected
    2. Assets/Main.cs(27,45): error CS0119: Expression denotes a `type', where a `variable', `value' or `method group' was expected
    btw the error codes is on the Debug Logs themselves. Debugging shows that "Player is a type, but is used like a variable".
     
  6. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    Can you post the complete Main script again please?
     
  7. Shramper

    Shramper

    Joined:
    Jun 1, 2013
    Posts:
    5
    Hey, sorry I figured out the problem, not the initial one though. Player1 = null and so forth needed to be player1Obj. But I'm still getting errors. I'll try to elaborate.

    I have 2 classes for each player that are essentially the same, to check for Ground Collision. This is so the jumps for the characters work out, as well as specifically for attacking. I'm getting an error I've initially got which started the issue, and after fixing eventually lead to this thread.


    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class isGroundCheckPlayer2 : MonoBehaviour {
    5.  
    6.     private Player2 player;
    7.  
    8.     // Use this for initialization
    9.     void Start () {
    10.    
    11.         player = gameObject.GetComponentInParent<Player2>();
    12.  
    13.     }
    14.  
    15.     void OnTriggerEnter2D(Collider2D col)
    16.     {
    17.  
    18.         player.isGrounded = true;
    19.  
    20.     }
    21.  
    22.     void OnTriggerStay2D(Collider2D col)
    23.     {
    24.  
    25.         player.isGrounded = true;
    26.  
    27.     }
    28.  
    29.     void OnTriggerExit2D(Collider2D col)
    30.     {
    31.  
    32.         player.isGrounded = false;
    33.  
    34.     }
    35. }
    36.  
    And the error:

    Code (CSharp):
    1. NullReferenceException: Object reference not set to an instance of an object
    2. isGroundCheckPlayer2.OnTriggerEnter2D (UnityEngine.Collider2D col) (at Assets/isGroundCheckPlayer2.cs:18)
    3.  
     
  8. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    I'm completely lost as to why you need multiple copies of the same script to handle the same behaviour on different characters.. Line 11 in "isGroundCheckPlayer2 " is obviously failing to retrieve the Player2 component on your gameObject.
     
  9. Shramper

    Shramper

    Joined:
    Jun 1, 2013
    Posts:
    5
    You know what, I took a few days break from this, and I'm going to go over everything I've done... try to slim everything down. The Duplicate Ground Check scripts are a bit confusing, and I forgot why I did it. Probably because I wanted to refer specifically to player 2.

    I also wanted to clarify that the duplicate script for player1, being player2, was so I can have it use different input keys. I don't know how I'd do it otherwise, other than possibly setting the inputs in Main somehow.

    I'll go over everything again and make sure everything makes SENSE first, before I ask for help. Thanks for the help anyway! Really appreciate it!
     
  10. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    Make a base class that has the job for updating the position of the player. Derive from it and implement an abstract method that will return the value of the input to the base class. If you would like examples let me know. You could join my discord channel as well(see my signature) if you would rather talk in real time.