All sprites in grid changing

I’m working on a tile-based factory game, and it is set up so that you can drag items from tile to tile. My issue is that when you drop an item on a tile, the sprite renderers of all the tiles change, instead of only the tile you dropped the items on. The items are stored in an itemstack class, and there is a tile class that contains an itemstack.

The functionality of the grid works fine, it’s just the sprite renderers and the code involved in them.

Here are the two classes:
Itemstack:

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

[System.Serializable]
public class ItemStack
{
    public int ID;
    public int count;
    public string name;
    public Sprite sprite;
}

Tile:

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

[System.Serializable]
public class Tile
{
    public int id;
    public int[] data;
    public string name;
    public Sprite sprite;
    public ItemStack item;
    public int storage;
}

And here is the script for the itemstack’s renderer:

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

public class ItemstackRender : MonoBehaviour
{
    public int x;
    public int y;
    public SpriteRenderer spriteRenderer;
    public Sprite sprite;
    public GameObject GBuilder;
    private GridBuilder GB;
    public ItemStack item;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if (GB == null)
        {
            GB = GBuilder.GetComponent<GridBuilder>();
        }
        item = GB.Retrieve(x, y).item;
        if (item.ID != 0)
        {
            sprite = item.sprite;
            spriteRenderer.sprite = sprite;
        }
    }
}

The grid class:

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

[System.Serializable]
public class GridBuild
{
    private int width;
    private int height;
    private float cellSize;
    private Tile[,] gridArray;

    public GridBuild(int width, int height, float cellSize, Tile baseTile)
    {
        this.width = width;
        this.height = height;
        this.cellSize = cellSize;

        gridArray = new Tile[width, height];
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                Vector3 CellPos = GetWorldPosition(x, y);
                gridArray[x, y] = baseTile;
            }
        }
    }

    private Vector3 GetWorldPosition(int x, int y)
    {
        return new Vector3(x, y) * cellSize;
    }

    private void GetXY(Vector3 worldPosition, out int x, out int y)
    {
        x = Mathf.RoundToInt(worldPosition.x / cellSize);
        y = Mathf.RoundToInt(worldPosition.y / cellSize);
    }
    public void SetValue(int x, int y, Tile value)
    {
        if (x >= 0 && y >= 0 && x < width && y < height)
        {
            gridArray[x, y] = value;
        }
    }
    public void SetValue(Vector3 worldPos, Tile value)
    {
        int x, y;
        GetXY(worldPos, out x, out y);
        SetValue(x, y, value);
    }
    public Tile GetValue(int x, int y)
    {
        if (x >= 0 && y >= 0 && x < width && y < height)
        {
            return gridArray[x, y];
        }
        return null;
    }
    public Tile GetValue(Vector3 worldPos)
    {
        int x, y;
        GetXY(worldPos, out x, out y);
        return GetValue(x, y);
    }
}

And lastly, the grid builder:

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

public class GridBuilder : MonoBehaviour
{
    public Tile baseTile;
    public GameObject baseCell;
    public int width;
    public int height;
    public float cellSize;
    public GridBuild grid;
    // Start is called before the first frame update
    private void Start()
    {
        grid = new GridBuild(width, height, cellSize, baseTile);
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                GameObject cell = Instantiate(baseCell, new Vector3(x, y) * cellSize, Quaternion.identity);
                TileRender tileRend = cell.GetComponent<TileRender>();
                ItemstackRender itemRend = tileRend.item.GetComponent<ItemstackRender>();
                tileRend.x = x;
                tileRend.y = y;
                itemRend.x = x;
                itemRend.y = y;
                tileRend.GBuilder = this.gameObject;
                itemRend.GBuilder = this.gameObject;
            }
        }
    }

    public void Build(Tile Value, Vector3 worldPos)
    {
        grid.SetValue(worldPos, Value);
    }
    public Tile Retrieve(Vector3 worldPos)
    {
        return grid.GetValue(worldPos);
    }
    public Tile Retrieve(int x, int y)
    {
        return grid.GetValue(x, y);
    }
}

If you want my other scripts, or context on them, I can provide, but I think I’ve narrowed down the issue to these scripts. I used part of CodeMonkey’s tutorial for a grid, but made lots of changes. (The tutorial is on youtube if you think it is relevant.)

It looks to me like the issue could be caused by the way you’re initializing and assigning values to the Tile instances in the GridBuild class. In the following loop, you’re assigning the same baseTile reference to every grid cell:

for (int x = 0; x < width; x++)
{
    for (int y = 0; y < height; y++)
    {
        Vector3 CellPos = GetWorldPosition(x, y);
        gridArray[x, y] = baseTile;
    }
}

This causes all the tile instances in the grid to share the same memory reference, and when you update one tile, it affects all other tiles in the grid. To fix this issue, you should create a new instance of the Tile class for each grid cell. You can create a constructor in the Tile class to make this easier. Something like this (Warning pseudocode incomming):

[System.Serializable]
public class Tile
{
    public int id;
    public int[] data;
    public string name;
    public Sprite sprite;
    public ItemStack item;
    public int storage;

    // Add a constructor
    public Tile(Tile baseTile)
    {
        this.id = baseTile.id;
        this.data = baseTile.data;
        this.name = baseTile.name;
        this.sprite = baseTile.sprite;
        // Initialize a new ItemStack instance
        this.item = new ItemStack();
        this.storage = baseTile.storage;
    }
}

Now you can use that constructor to create nre Tile instances for each grid cell:

for (int x = 0; x < width; x++)
{
    for (int y = 0; y < height; y++)
    {
        Vector3 CellPos = GetWorldPosition(x, y);
        gridArray[x, y] = new Tile(baseTile);
    }
}

Let me know if that gets you closer to an answer.