List gets updated even if I don't call it

Hi, I’m creating a kind of tower defense game and this is my script for moving an enemy. It’s attached to an enemy that gets spawned after a path is created. It gets List from PathCreator script on start and only there, the list is also private.

So in my mind - After spawning an enemy, he gets a path and he follows this path even if PathCreator creates a new one because I assign it only on Start.

This is how I want it to work, but for some reason when I create a new path in PathCreator enemy follows it instead of following the one he got on Start().

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class EnemyMover : MonoBehaviour
{
    [HideInInspector] public Grid.Sides side;

    List<Waypoint> path = new List<Waypoint>();

    NavMeshAgent agent;

    int currentwaypoint = 1;

    private void Start()
    {
        path = FindObjectOfType<PathCreator>().GetPath(side);

        agent = GetComponent<NavMeshAgent>();
    }

    private void Update()
    {
        Move();
    }

    private void Move()
    {
        if (currentwaypoint == path.Count)
        {
            Destroy(gameObject);
            return;
        }

        agent.destination = path[currentwaypoint].transform.position;
        path[currentwaypoint].SetColor(Grid.Sides.top, Color.black);

        if (IsDestinationReached())
        {
            SetNextWaypoint();
        }
    }

    private void SetNextWaypoint()
    {
        currentwaypoint += 1;
    }

    private bool IsDestinationReached()
    {
        if (Vector3.Distance(transform.position, agent.destination) < 1.3f) return true;
        return false;
    }
}
    public List<Waypoint> GetPath(Grid.Sides getPathSide)
    {
        if (getPathSide == Grid.Sides.top)
        {
            return topPath;
        }

        if (getPathSide == Grid.Sides.bottom)
        {
            return bottomPath;
        }

        return null;
    }

This bug isn’t going to affect my game in any way because I’m not going to allow new paths get created after enemies start spawning but I’m curious why it’s working like that and I’d like to understand it.

Lists are reference types. Assigning a List just says “I’m that list over there.”

So after you assign the path in Start(), if anyone changes the contents of topPath or bottomPath, they are modifying the same path that path points to.

If you want to fix it, one way is to make a fresh list in Start():

path = new List<Waypoint>( FindObjectOfType<PathCreator>().GetPath(side));

EDIT: I bozo-ed the term value vs reference… fixed.

1 Like

List, like all classes in C#, is a reference type. When you assign a value to a List variable, you aren’t making a copy of the list, you are just pointing that variable towards some List that already exists. If that List is subsequently modified, the variable will “see” those modifications.

3 Likes

It explains a lot, thank you for quick replies