0
\$\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\$
  • \$\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\$ – LifGwaethrakindo Jul 16 '18 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\$ – StuckInPhD Jul 17 '18 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\$ – LifGwaethrakindo Jul 17 '18 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\$ – StuckInPhD Jul 17 '18 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\$ – LifGwaethrakindo Jul 17 '18 at 0:18
2
\$\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\$
  • \$\begingroup\$ Works perfectly, many thanks. So my mistake was not creating a gameobject before hand and assigning it to the respective array slot. \$\endgroup\$ – StuckInPhD Jul 17 '18 at 23:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.