Items on List being removed?

Hi I’m having trouble with this code because the items of the list sWaypoints are being deleted?,
I checked the references and with debugs, the ManualStart is only being called once, also the only references of sWaypoint are the ones on this script. So why is this happening?

Thank you in advance.

using System.Collections.Generic;
using UnityEngine;

public class Spawner : MonoBehaviour
{
    public Transform monstersParent;
    public int[] monstersInv = new int[27];
    public GameObject[] monsters = new GameObject[27];
    private List<Vector3>[] sWaypoints = new List<Vector3>[3];

    private int pathNumber = 0;
    private int tempPathNumber = 0;
    private float waitTime;

    private void Awake()
    {
        enabled = false;
    }

    public void ManualStart(List<Vector3[]> _waypoints)
    {
        sWaypoints[0] = new List<Vector3>();
        sWaypoints[1] = new List<Vector3>();
        sWaypoints[2] = new List<Vector3>();
        for (int i = 0; i < _waypoints.Count; i++)
        {
            sWaypoints[0].Add(_waypoints[i][0]);
            sWaypoints[1].Add(_waypoints[i][1]);
            sWaypoints[2].Add(_waypoints[i][2]);
        }

        enabled = true;

        for (int i = 0; i < 5; i++)
        {
            Debug.Log("LIST 0: " + sWaypoints[0][i]);
        }
    }

    private void Update()
    {
        if (waitTime > 0) 
        { 
            waitTime -= Time.deltaTime;
            return;
        }

        Debug.Log("LIST 0: " + sWaypoints[0][0]);
        Debug.Log("LIST ///////////////////////// ");

        #pragma warning disable CS0162 // Unreachable code detected
        for (int i = 0; i < monstersInv.Length; i++)
        {
            if (monstersInv[i] == 0) { return; }

            // Asign a random path
            do { tempPathNumber = Random.Range(0, 3); }
            while (tempPathNumber == pathNumber);
            pathNumber = tempPathNumber;
            GameObject o = Instantiate(monsters[i], sWaypoints[pathNumber][0], Quaternion.identity, monstersParent);
            o.GetComponent<Minion>().MinionManualStart(sWaypoints[pathNumber]);

            monstersInv[i] -= 1;
            waitTime = 0f;
            waitTime = Random.Range(monsters[i].GetComponent<Minion>().spawnTime * 0.75f, monsters[i].GetComponent<Minion>().spawnTime * 1.25f);
            break;
        }    
        #pragma warning restore CS0162 // Unreachable code detected
    }
}

image

sWaypoints is an array of lists. Do you mean to say that some of the lists referenced in sWaypoints are getting their elements removed?

You’re passing a list into MinionManualStart on line 61. This method could be modifying things.

How exactly are you determining that elements are being removed? The log on line 48 only logs one element. It would be productive to use a loop and print all the elements in the list. You might be confused by your code and thinking there’s one element remaining because you’re only printing one.

Yea but how are the items being modified when I’m passing them? or how could I prevent the list from being modified?

I already did the loop and log the entire list every iteration and they’re indeed, being removed, I just showed five first items of the list on the screenshot because the list has like a hundred or two items.

Also, I am logging the same first item in the list in every iteration and as you can see in the screenshot, if nothing is changed, the logged item should be the same, but instead it is logging the next item on the list. (the first being removed and now sWaypoints[0][0] is now the second original item and so on)

On line 61, you’re passing an entire list, so anything is fair game as far as MinionManualStart is concerned. MinionManualStart or other code called in it could be storing the list as its own and modifying it. If you want to make changes, make a copy of it on either side (new List<Vector3>(oldList), in the place where you store a list or when you pass it to MinionManualStart).

Look, here’s the code on the other script:

I already created a list named waypoints in this script, assigned the list passed via MinionManualStart and then modified it, but how could be affecting the original one? Am I missing something here?


    private List<Vector3> waypoints = new List<Vector3>();

    public void MinionManualStart(List<Vector3> _waypoints)
    {     
        waypoints = _waypoints;
        waypoints.RemoveAt(0); // Delete Spawnpoint from list
        waypointIndexMax = waypoints.Count;

        switch (minion)
        {
            case MinionType.Slime:
                targetRange = 0.25f;
                SlimeStartAnimation();
                GetComponent<Animator>().speed = speed;

                int materialPicker = Random.Range(1, 4);
                if (materialPicker == 2)
                {
                    transform.GetChild(1).GetComponent<Renderer>().material = Resources.Load<Material>("Prefabs/Characters/Slime/Slime 2");
                    ParticleSystem.MainModule particleSystem = transform.GetChild(1).GetComponent<ParticleSystem>().main;
                    particleSystem.startColor = new Color(0.2f, 1, 0.2f);
                }
                else if (materialPicker == 3)
                {
                    transform.GetChild(1).GetComponent<Renderer>().material = Resources.Load<Material>("Prefabs/Characters/Slime/Slime 3");
                    ParticleSystem.MainModule particleSystem = transform.GetChild(1).GetComponent<ParticleSystem>().main;
                    particleSystem.startColor = new Color(0.2f, 1, 0.6f);
                }

                enabled = false;
                break;

            default:
                targetRange = 0.5f;
                break;
        }
    }

Lists are instances of classes, which are reference types. Passing a list means you’re passing a reference to the same object in memory. Adding/removing/modifying things in the list from a passed variable will be doing things on the one object both variables are referencing. The _waypoints parameter in MinionManualStart, the waypoints field in the Minion script, and the passed array element of sWaypoints in your Spawner script all are referencing the same object. You need to break that connection by creating a new list that has the same list content but is an entirely new object (as I showed in the previous message, using a list constructor).

This is some of the fundamental stuff in C#, so it’s important you get a handle on this sooner rather than later, it can bite you in the arse (as has happened here) if you’re not careful.

Oh, I didn’t know that, thank you so much it worked!

It’s all good, other languages can be quite different. Here’s some reading:

alue Types vs Reference Types: