Search Unity

Array of GameObjects [solved]

Discussion in 'Scripting' started by JonasNielsen, Apr 12, 2010.

  1. JonasNielsen

    JonasNielsen

    Joined:
    Apr 12, 2010
    Posts:
    4
    Hi all.

    I'm having some trouble adding and especially retrieving GameObjects from an array. Here is a code sample:

    Code (csharp):
    1.  
    2. var ballPrefab : GameObject;
    3. var balls = new Array();
    4. function Start() {
    5.  
    6. // Instantiate ball for test-purpose
    7. var newBall : GameObject = GameObject.Instantiate(ballPrefab,Vector3(10.0,0.0,10.0),Quaternion.identity) as GameObject;
    8. balls.Add(newBall);
    9. }
    10.  
    11. function findClosestBall(ball_x : int, ball_y : int) : GameObject {
    12.  
    13. for (var i=0; i < balls.length; i++){
    14.     var ball : GameObject = balls[i] as GameObject; // THIS MAKES ERROR
    15.     var ballVector : Vector3 = (ball.transform.position);
    16. }
    17.  
    18. return null;
    19. }
    20.  
    The error I'm getting is: NullReferenceException: Object reference not set to an instance of an object

    What am I doing wrong? What is the correct way to store an array of GameObjects?

    Thanks, Jonas
     
  2. AndrewGrayGames

    AndrewGrayGames

    Joined:
    Nov 19, 2009
    Posts:
    3,821
    Try this:

    Code (csharp):
    1. var ballPrefab : GameObject;
    2. var balls : GameObject[];  // :D
    3.  
    4. function Start()
    5. {
    6.   // Instantiate ball for test-purpose
    7.   var newBall : GameObject = GameObject.Instantiate(ballPrefab,Vector3(10.0,0.0,10.0),Quaternion.identity);
    8.   balls.Add(newBall);
    9. }
    10.  
    11. function findClosestBall() : GameObject
    12. // You don't need an (x,y) argument list for this, I hope.
    13. {
    14.   // You only need to declare a variable once.
    15.   var ball : GameObject;
    16.   var ballVector : Vector3;
    17.  
    18.   for (var i=0; i < balls.length; i++)
    19.   {
    20.     ball = balls[i];  // This no longer makes errors.
    21.     ballVector = ball.transform.position;
    22.   }
    23.  
    24.   // It appears you have not completed the function.
    25.   return null;
    26. }
    A few things:

    -You really only need to declare variables once per function, most of the time.
    -You don't have to cast when you declare a variable to be of a certain type.
    -You don't have to declare an array as an untyped variable of an Array(). You can add [] to the end of the type to make Unity recognize it as a dynamic array, and you can add [#] to make it a static array.

    EDIT: Now, I'm going to show you a few tricks!

    Code (csharp):
    1. function FindClosestBall() : GameObject
    2. {
    3.   var myPos : Vector3 = transform.position;
    4.   var closestBall : GameObject = null;
    5.   var curDist : float;  // These two are distances.
    6.   var testDist : float;
    7.  
    8.   // This is a better way to scan a dynamic array.
    9.   // It's like ForEach in C#.
    10.   for( var ball in balls )
    11.   {
    12.     // Initializing condition...
    13.     // If closestBall is null, the first ball becomes
    14.     // the ball we start judging from.
    15.     if( closestBall == false )
    16.     {
    17.       closestBall = ball;
    18.       testDist = Vector3.Distance( transform.position, closestBall.transform.position );
    19.     }
    20.  
    21.     // Get the distance to this ball...
    22.     curDist = Vector3.Distance( transform.position, ball.transform.position );    
    23.  
    24.     // Real test...
    25.     if( curDist < testDist )
    26.     {
    27.       closestBall = ball;
    28.       testDist = Vector3.Distance( transform.position, closestBall.transform.position );
    29.     }
    30.   }
    31.  
    32.   return closestBall;
    33. }
    This code looks longer - and character-for-character is longer - but it works closer to what you're intending. You can use a For loop in Unity JavaScript in similar fashion to ForEach in C#. Additionally, for this problem Vector3.Distance() is your friend.

    I hope all this helps!
     
  3. JonasNielsen

    JonasNielsen

    Joined:
    Apr 12, 2010
    Posts:
    4
    Asvarduil, thank you very much for your helpful reply. It is really appreciated!

    Please see update further down

    I'm still working to make all of this work.
    I'm experiencing a problem with they GameObject[] way of doing an array:

    Code (csharp):
    1.  
    2. var ballPrefab : GameObject;
    3. var balls : GameObject[];
    4.  
    5. function Start()
    6. {
    7.     // Register listeners
    8.     Messenger.instance.Listen("ballcoordinate", this);
    9.    
    10.     // Instantiate ball for test-purpose
    11.     var newBall : GameObject = GameObject.Instantiate(ballPrefab,Vector3(10.0,0.0,10.0),Quaternion.identity);
    12.     balls.Add(newBall);
    13. }
    the last line above results in an error:
    "'Add' is not a member of '(UnityEngine.GameObject)'. "
    which sounds pretty strange to me? If Unity handles the variable as a dynamic array, isn't it then able to handle add methods?

    EDIT:

    I avoided this problem by initializing a specific size of the array in the start function. However, its still a mystery to me why it isn't possible to extract an object from the array. The code again:
    Code (csharp):
    1.  
    2. var ballPrefab : GameObject;
    3. var balls : GameObject[];
    4.  
    5. function Start()
    6. {
    7.     balls = new GameObject[100];
    8.     // Register listeners
    9.     Messenger.instance.Listen("ballcoordinate", this);
    10.    
    11.     // Instantiate ball for test-purpose
    12.     var newBall : GameObject = GameObject.Instantiate(ballPrefab,Vector3(10.0,0.0,10.0),Quaternion.identity);
    13.     balls[balls.length] = newBall;
    14. }
    15.  
    16. function findClosestBall(ball_x : int, ball_y : int) : GameObject {
    17.    
    18.     var ball : GameObject;
    19.     var ballVector : Vector3;
    20.    
    21.     for (var i=0; i < balls.length; i++)
    22.     {
    23.         ball = balls[i]; // HERE'S THE ISSUE
    24.         ballVector = ball.transform.position;
    25.     }
    26.    
    27.     return null;
    28. }
    29.  
    When calling findClosestBall a null exception is thrown:
    NullReferenceException: Object reference not set to an instance of an object - referring to ball = balls;

    Thanks again,
    Jonas
     
  4. dbp

    dbp

    Joined:
    Mar 3, 2010
    Posts:
    324
    these built-in arrays don't work exactly the same way as the javascript arrays, the built-in arrays indeed do not have an Add()-function, instead you have to specify the position in the array where you want to put it, in your case

    balls[balls.length] = newBall;

    this way you place the new ball at the end of the array
     
    Kissta likes this.
  5. JonasNielsen

    JonasNielsen

    Joined:
    Apr 12, 2010
    Posts:
    4
    Thanks, dbp, that was what I discovered :)
    It doesn't fix everything unfortunately. Please see the update in my previous post.

     
  6. dbp

    dbp

    Joined:
    Mar 3, 2010
    Posts:
    324
    now you are not using a dynamic array anymore, while avoiding dynamic arrays is usually faster, this is what's causing the problem.

    balls = new GameObject[100];

    by using this, you set the length of the array to 100, so in the start function, you put the ball into the array at index 100, later you are trying to access the position 0, which is empty.

    if you want to use this code, you have to use
    balls[0] = newBall;
    in the start function
     
  7. JonasNielsen

    JonasNielsen

    Joined:
    Apr 12, 2010
    Posts:
    4
    I wrestled around with it, and finally made it work. The solution is simple, and to be honest pretty much as I expected. The great savior was instantiating an object and then add the gameobject for that object to an array.
    I ended up using ArrayList because of the convenient way it works with .Add .RemoveAt.
    Here's a working example:

    Code (csharp):
    1.  
    2. var balls : ArrayList;
    3.  
    4. function Start()
    5. {
    6.     balls = new ArrayList();
    7.    
    8.     // Instantiate ball for test-purpose
    9.     var newBall = Instantiate(ballPrefab,Vector3(10.0,0.0,10.0),Quaternion.identity);
    10.     balls.Add(newBall.gameObject); // Notice .gameObject
    11. }
    12.  
    13. function findClosestBall(ball_x : int, ball_y : int) : GameObject {
    14.    
    15.     var closestBall         : GameObject;
    16.     var shortestDistance    : float = 9999;
    17.     var ballPos             : Vector3;
    18.     var coordinatePos       : Vector3;
    19.     var distanceVector      : Vector3;
    20.    
    21.     for(var ball : GameObject in balls){
    22.         ballPos = ball.transform.position;
    23.         coordinatePos = Vector3(ball_x, GameController.y_height, ball_y);
    24.         distanceVector = ballPos - coordinatePos;
    25.        
    26.         if (distanceVector.magnitude < shortestDistance){
    27.             closestBall = ball;
    28.             shortestDistance = distanceVector.magnitude;
    29.         }
    30.     }
    31.     return closestBall;
    32. }
    33.  
    Thanks to all the guys who helped me crack the code.
     
  8. IMTRIGGERHAPPY9

    IMTRIGGERHAPPY9

    Joined:
    Jul 27, 2011
    Posts:
    35
    hey i need some help.... i know its kinda tacky posting questions on dead forum posts but i am hoping somebody can help me out, i dont understand why it wont let me put these objects in this array i created can anybody help me?

    essentially i am trying to create a 10x10 grid, the code is pretty self explanatory.

    p.s. i am hoping the post doesnt screw the code all up, and if you have any questions please ask!

    var instantiateObject : Transform;

    var gridX = 10;
    var gridY = 10;


    function Start () {

    var map : GameObject[,] = new GameObject[gridX,gridY];


    for ( var x = 0; x < gridX; x++){

    for (var y = 0; y < gridY; y++){

    var myName = Instantiate(instantiateObject, Vector3(x *.5,0,y * .5), Quaternion.identity);


    myName.name = "x: " + x + "y: " + y;

    if (x < 9)
    var xInArray = instantiateObject;

    else
    var yInArray = instantiateObject;

    //map[xInArray,yInArray];

    }

    }


    Debug.Log(map);
    Debug.Log(yInArray.name);
    Debug.Log(xInArray.name);
    }
     
  9. rahulpatil6220375

    rahulpatil6220375

    Joined:
    Dec 10, 2018
    Posts:
    19
    how to store a initiate value remove it??