Creating a Vector3 array of object positions

So, what I’m trying to accomplish with this piece of script is to access the positions of an array of objects. The objects are already in the array and when I log the individual positions in the for loop, they log correctly in the console, but it gives me the “Object Reference not set to an instance of an object” error.

Here’s the code:

using UnityEngine;
using System.Collections;

public class CylinderChecker : MonoBehaviour {



    public GameObject[] Pins;
    // Use this for initialization
    public int pinCount;
    private Vector3[] positions;
    void Start () {
       
        for (int i = 0; i < 10; i++) {
            Vector3 position = Pins [i].transform.position;
            positions [i] = position;
            Debug.Log (positions [i]);
        }

   
    }
    }

The eventual goal of this script is to again access the new positions after they’ve been knocked over and compare that to the original positions from the positions[ ] array in order to count a score for each cylinder knocked over. If there is a better way to do this, I am open to suggestions, but this was what I was working with.

Any feedback would be very helpful.

1 Like

It because of how Arrays work. When you type this line:

int[] someInts = new int[5];

C# creates a small box of memory labeled someInt. Then it creates a larger box of memory that is 5x 4bytes long. It puts the address of this memory into the small box labled someInt. Then when you type someInt[0] it looks up this address goes to the big box and returns the first int you saved there:

Now when you type this :

public GameObject[] Pins;

and you set its number to say 5. Unity is writing this line behind the scenes:

Pins = new GameObject[5];

So compiler is again setting up a big box to hold all those GameObjects somewhere. But if a field is private and you type this:

private Vector3[] positions;

Then you’ve told the compiler to make the small box positions, but you didn’t tell it how many. So positions has the value of null in it. That is why you are getting the null reference error. To be honest i’m surprised the Debug.Log is actually giving you a valid Vector3, and not a null reference as well. To fix the problem you can do this:

void Awake()
{
       positions = new Vector3[Pins.Length];
}

void Start()
{
      for (int i=0;i<Pins.Length;i++)

This will set your positions to however big Pins is set to in the Inspector. It will also let you change Pins to a number other than 10, so your Start code will work no matter how many pins you have.

3 Likes

I prefer to use generic Lists in almost every case where I don’t care about specific index. They’re not as performant as arrays, but much more intuitive to work with.

using UnityEngine;
using System.Collections.Generic; // generic collection types
using System.Linq; // Linq functions

public class CylinderChecker : MonoBehaviour {
    public List<GameObject> Pins; // set up in inspector

    private List<Vector3> positions;

    private void Start() {
        positions = new List<Vector3>(); // create new empty list

        foreach(GameObject go in Pins) {
            positions.Add(go.transform.position);
        }

        // or with for loop syntax:

        for(int i = 0; i < Pins.Count; i++) {
            positions.Add(Pins[i].transform.position);
        }

        // or with Linq
        Pins.ForEach(go => positions.Add(go.transform.position));

        // also linq
        positions = Pins.Select(go => go.transform.position).ToList();
    }
}

Edit:
added some Linq examples for this context

Lists are nice, when you want to add and remove objects without having to worry about holes, but in the end it all depends on the usecase.

If you know, for example, that you will always have the same number of objects, use an array. There is no need for the List-Overhead. If you want to add/remove at the start or end of the collection, use a stack or queue, depending on which end you want to remove from.

Independent of what type of collection you use, I’d advise getting aquainted with Linq (just don’t treat it as a magic hammer…not every problem is a nail). You can do some neat stuff with it, albeit you sacrifice a little bit of performance, but premature optimization is useless, anyway.

using System.Linq;

GameObject[] Pins;
Vector3[] positions;

void Start() {
    positions = Pins.Select(p => p.transform.position).ToArray();
}
4 Likes

Thank you!

Hey,

I could not able to figure out why I need to provide third argument in getting position of an object in c++, but not in Lua scripts. I am using built-in plugin for ros.

CODE: SELECT ALL · EXPAND

using sim_vector_t = std::array<float,3>;

m_jointHandle = simCreateJoint(10,5, 1, nullptr, nullptr, nullptr);
sim_vector_t pos {0.0,0.0,0.0}; //dummy x,y,z values
//trying to get the position of my robot w.r.t to world frame.

auto position = simGetObjectPosition(GetBaseHandle(),-1,pos.data());

what could be the value of pos1?, I do not know what to put here.

could you help me in providing the third argument. I went through documentation, it is just mentioned simFloat* position, but no information about which position values.
In documentation:

objectHandle: handle of the object
relativeToObjectHandle: indicates relative to which reference frame we want the position. Specify -1 to retrieve the absolute position, sim_handle_parent to retrieve the position relative to the object’s parent, or an object handle relative to whose reference frame we want the position.
position: pointer to 3 values (x, y and z)

I don’t know what should be the values of x,y,z?
Thanks in advance

Rather than hijacking some random thread from 2016, which is completely against forum rules, please start your own post. It’s FREE.

When you make your new post, keep these things firmly in mind:

How to report your problem productively in the Unity3D forums:

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

If you post a code snippet, ALWAYS USE CODE TAGS:

How to use code tags: https://discussions.unity.com/t/481379