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

Confused with c# script - Reference to object not being updated

Discussion in 'Scripting' started by JohnnyRey, Jul 3, 2013.

  1. JohnnyRey

    JohnnyRey

    Joined:
    Jan 26, 2013
    Posts:
    16
    Hey Guys,

    So I've got something like this:

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class GUIScript : MonoBehaviour {
    5.    
    6.     public Transform[] PlayerTransformList;
    7.     Transform player1;
    8.     Transform player2;
    9.     Transform player3;
    10.     Transform player4;
    11.  
    12.     // Use this for initialization
    13.     void Start () {
    14.  
    15.         PlayerTransformList = new Transform[4];
    16.         PlayerTransformList[0] = player1;
    17.         PlayerTransformList[1] = player2;
    18.         PlayerTransformList[2] = player3;
    19.         PlayerTransformList[3] = player4;
    20.                
    21.     void Update () {
    22.         if (Input.GetButtonDown("Start1")){
    23.             if (PlayerList[0] == "Press Start"){
    24.                 PlayerList[0] = "Player 1";
    25.                 player1 = Instantiate(tank,spawnPoints[Random.Range(0,spawnPoints.Length)].transform.position,rotTemp.transform.rotation)as Transform;
    26.                 player1.name = "Player 1";
    27.                 player1.GetComponent<PlayerScript>().playerNum = 1;
    28.                 this.GetComponent<CameraFollow>().target = player1;
    29.                
    30.             }
    31.         }
    If I then run through the PlayerTransform Array, PlayerTransformList[0] (which should have a reference to the player1 Transfrom) isn't updated, and still shows as being null.

    Am I missing something?
     
  2. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Yes... player1 is null when you add it to the player transform list, so there is nothing to reference. You'll have to reset the PlayerTransformList element when you create the players... i.e.:

    Code (csharp):
    1.  
    2. if (Input.GetButtonDown("Start1")){
    3.             if (PlayerList[0] == "Press Start"){
    4.                 PlayerList[0] = "Player 1";
    5.                 player1 = Instantiate(tank,spawnPoints[Random.Range(0,spawnPoints.Length)].transform.position,rotTemp.transform.rotation)as Transform;
    6.                 player1.name = "Player 1";
    7.  
    8.  
    9.                //*** This... right here
    10.                 PlayerTransformList[0] = player1;
    11.  
    12.  
    13.                 player1.GetComponent<PlayerScript>().playerNum = 1;
    14.                 this.GetComponent<CameraFollow>().target = player1;            
    15.             }
    16.   }
    17.  
    There probably isn't a reason to keep both the variable and the array since they'll reference the same object... just store the objects in the array and forget the properties unless you need them for something else.
     
  3. JohnnyRey

    JohnnyRey

    Joined:
    Jan 26, 2013
    Posts:
    16
    Ah, ok. This is my inexperience with programming showing - That makes sense now. So if It wasn't null when I first added it, I wouldn't have this issue, correct?
     
  4. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Not exactly... here's a good example:

    Code (csharp):
    1.  
    2. var p1 = new SomeClass();
    3. var p2 = p1;
    4.  
    5. var someList = new SomeClass[1];
    6. someList[0] = p1;
    7.  
    So, p1 is a new class instance, p2 is set equal to p1, and I put p1 into the first element of an array. There is one single instance of SomeClass. p1, p2 and someList[0] all have a pointer to that object in memory (hence ReferenceType). So now I do this again;

    Code (csharp):
    1.  
    2.    p1 = new SomeClass();
    3.  
    Now... I've created a NEW instance of SomeClass and assigned it to p1. p2 and someList[0] still reference the old instance so it was never really gone... so the following would apply:

    Code (csharp):
    1.  
    2.  
    3. //This will be true
    4. someList[0] == p2;
    5.  
    6. //This will be false
    7. p1 == p2;
    8.  
    9. //This will also be false
    10. p1 == someList[0];
    11.  
    12.  
    Before I called p1 = new SomeClass() the second time... all three of the above would have been true. This is how you could easily end up with memory leaks as well. You have to be aware of all the objects that reference your object.

    Consider this though... let's same SomeClass had a string property called SomeProperty and it defaulted to "foo". If you did not reassign p1 (just use the first code block) and set:

    Code (csharp):
    1.  
    2. p1.SomeProperty = "bar";
    3.  
    That property would be updated for p2 and someList[0] as well since they all three point to the same object in memory. Another way you can protect yourself a little bit is to implement iDisposable on your classes. So if you called p1.Dispose (instead of p1 == null), then your SomeClass() object would be marked and garbage collected and would become null for p2 and someList[0] as well.

    Your best bet is to just use the array and not the properties... this will make it much less complex and you won't need to manage so carefully to make sure you're not leaving objects hanging around and that your references update properly.
     
  5. JohnnyRey

    JohnnyRey

    Joined:
    Jan 26, 2013
    Posts:
    16
    Wow! Thank you for the detailed explanation. My mistake was thinking that I could "reference a reference" - when clearly that's not the case, as it simply references the actual object. Thank you very much!
     
  6. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    You're very welcome. :)