Search code examples
c#unity-game-engineinstance

If I replace the only reference to an instance of a class in an array, does it destroy the original instance?


I am trying to create a grid based map by instancing a class associated with each tile, and storing them in an array. The GenerateBattlefieldTiles() method simply generates an entire map of generic tiles, which will be replaced with later methods. Right now I am working on a path generator, and am wondering if replacing an instance in the array will destroy the instance, since the array is the only reference to said instance, or if I have to destroy the instance before replacing it.

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

public class BattlefieldManager : MonoBehaviour
{
    public int pathWaypointCount;
    public List<PathTile> paths;
    public BattlefieldTile[,] battlefieldTiles;
    public int xSize;
    public int ySize;
    public int seed;
    public enum TileType { Path, Obstacle, Generic, Buildable }

    // Start is called before the first frame update
    void Start()
    {

    }

    void GenerateBattlefieldTiles()
    {
        battlefieldTiles = new BattlefieldTile[xSize, ySize];
        for (int y = 0; y < battlefieldTiles.GetLength(1); y++)
        {
            for (int x = 0; x < battlefieldTiles.GetLength(0); x++)
            {
                Vector2 tilePosition = new Vector2(x - xSize / 2, ySize / 2 - y);
                battlefieldTiles[x, y] = new BattlefieldTile(TileType.Generic, tilePosition, new Vector2(x, y));
            }
        }
    }

    void GenerateWaypoints()
    {
        Random.InitState(seed);
        int entryYValue = Random.Range(1, ySize - 1);
        int exitYValue = Random.Range(1, ySize - 1);
        PathTile entryTile = new PathTile(TileType.Path, new Vector2(-xSize / 2, battlefieldTiles.GetLength(1) / 2 - entryYValue), new Vector2(0, entryYValue));
        paths.Add(entryTile);
        battlefieldTiles[0, entryYValue] = entryTile;
        PathTile exitTile = new PathTile(TileType.Path, new Vector2(xSize / 2, battlefieldTiles.GetLength(1) / 2 - exitYValue), new Vector2(xSize, exitYValue));
        battlefieldTiles[xSize, exitYValue] = exitTile;

        while (paths.Count < pathWaypointCount)
        { 
            Vector2 newWaypoint = new Vector2(Random.Range(1, xSize - 1), Random.Range(1, ySize - 1));
            int i = 0;
            foreach (PathTile path in paths)
            {
                if (newWaypoint == path.arrayRef)
                {
                    return;
                }
                if (Mathf.Abs(newWaypoint.x - path.arrayRef.x) == 1 && Mathf.Abs(newWaypoint.y - path.arrayRef.y) == 1)
                {
                    i++;
                    if (i >= 2)
                    {
                        return
                    }
                }
                PathTile pathTile = new PathTile(TileType.Path, new Vector2(newWaypoint.x - xSize / 2, ySize / 2 - newWaypoint.y), newWaypoint);
                paths.Add(pathTile);
                battlefieldTiles[Mathf.RoundToInt(newWaypoint.x), Mathf.RoundToInt(newWaypoint.y)] = pathTile;
            }
        }
    }
}

Solution

  • In short, yes it will get destroyed, through no other action from you. Eventually.

    The longer answer is that the instance, or to be more specific, the memory address of the object you were referencing, will become available for garbage collection. I don't know how long it takes for abandoned memory to get flagged for collection.

    I do know that if you intentionally set the object to null you could manually call the garbage collector to immediately clean it up. Don't do this though, because you can only call a full collection, and not a focused one on this specific object.

    As a general note outside of your specific case, if you have an object that has other resources it uses and you want to free those up more immediately, such as web connections or file locks, you should implement IDisposable. In the Dispose() method you would then clean up all those references. Then rather than just letting that object go out of scope you would call the dispose method on it to immediately clean up those resources. Otherwise they will remain open until the garbage collection gets around to it on its own schedule.