1
\$\begingroup\$

So I have a tower surrounded by 4 spawner gameobjects. I want to draw lines to all of them using LineRenderer. I wrote the following code to achieve this but for some reason I am getting NullReferenceException: Object reference not set to an instance of an object at the line myLines[i].transform.position = startPos;

public Transform towerPos;
GameObject[] myLines;

void DrawLines()
        {
            myLines = new GameObject[spawnpoints.Count];
            Vector3 startPos = towerPos.transform.position;
            for (int i = 0; i < spawnpoints.Count; i++)
            {

                myLines[i].transform.position = startPos;
                myLines[i].AddComponent<LineRenderer>();
                LineRenderer lr = myLines[i].GetComponent<LineRenderer>();
                lr.material = new Material(Shader.Find("Particles/Alpha Blended Premultiply"));
                lr.SetColors(Color.red, Color.red);
                lr.SetWidth(0.3f, 0.3f);
                lr.SetPosition(0, startPos);
                lr.SetPosition(1, spawnpoints[i].spawnPoint.transform.position);
                //GameObject.Destroy(myLine, duration);
            }
        }

The above function is called at Start(). The tower GameObject is dragged into the towerPos variable in the editor so dont know why its a null.

\$\endgroup\$
6
  • \$\begingroup\$ Because at Start you are initializing the array (new GameObject[spawnPoints.Count]), a new array is made, giving each slot a default value (this case null), so that is where the NullReferenceException comes from. Why don't you use spawnCount's list instead of that array? LineRenderer's methods take positions as parameters, so it does not matter whether it comes from an array or a list. \$\endgroup\$ Jul 16, 2018 at 23:52
  • \$\begingroup\$ Thanks for your input @LinkWindcrafter. Im not very familiar with Lists so would not know how to use it in this context. I know that at initialization it will have null values, but am I now populating that array index using myLines[i].transform.position = startPos;? This should overwrite the null, no? \$\endgroup\$ Jul 17, 2018 at 0:07
  • \$\begingroup\$ Maybe the provided list has a Count of 0, try debugging its count, if it has 0 as count, you must first make sure that list has something (Debug.Log("Count: " + spawnPoints.Count)) \$\endgroup\$ Jul 17, 2018 at 0:09
  • \$\begingroup\$ Its not empty, the debug statement gives a count of 4 which is the number of spawnpoints in my scene. \$\endgroup\$ Jul 17, 2018 at 0:13
  • \$\begingroup\$ Then is is the fact that the array is on its default state (all slots into null). So try to populate your array, using that same list as reference (example: myLines = spawnPoints.ToArray() instead of using the new keyword) \$\endgroup\$ Jul 17, 2018 at 0:18

1 Answer 1

3
\$\begingroup\$

In C#, new SomeReferenceType[length] doesn't create length number of objects of type SomeReferenceType. It creates an Array that could hold that many SomeReferenceType references, but initially contains nothing.

So, if you want to fill that array with actual objects, you need to assign them.

void DrawLines()
{
    myLines = new GameObject[spawnpoints.Count];
    Vector3 startPos = towerPos.transform.position;

    // Cache your material so you don't need to make so many copies.
    var material = new Material(Shader.Find("Particles/Alpha Blended Premultiply"));

    for (int i = 0; i < spawnpoints.Count; i++)
    {
        // FIRST: Create & assign your GameObject into the array slot.
        var lineObject = new GameObject("Line" + i);
        myLines[i] = lineObject;


        lineObject.transform.position = startPos;
        LineRenderer lr = lineObject.AddComponent<LineRenderer>();

        // No need to search for the component we just added!
        // LineRenderer lr = myLines[i].GetComponent<LineRenderer>();

        // Use sharedMaterial to be batching-friendly and avoid excess allocation.
        lr.sharedMaterial = material;

        lr.SetColors(Color.red, Color.red);
        lr.SetWidth(0.3f, 0.3f);
        lr.SetPosition(0, startPos);
        lr.SetPosition(1, spawnpoints[i].spawnPoint.transform.position);
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ Works perfectly, many thanks. So my mistake was not creating a gameobject before hand and assigning it to the respective array slot. \$\endgroup\$ Jul 17, 2018 at 23:46

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .