How to correctly store tile and terrain type data?

Greetings everyone!

I am building a hex tile game where hex is a piece of terrain and can be of different type, e.g. “Sand”, “Dirt”, “Water”. Therefore each hex can have different sprite and probably different properties, say Water is not walkable and Dirt gives -1 to speed.

I am a bit confused of correct storing the information about terrain types. Below I will show what I’ve come up with at the moment.

Tile game object

  • Has Sprite Renderer component attached

  • Has “Tile.cs” script attached with public property “Terrain Type”

  • Tile.cs calls helper class to set correct terrain sprite to Sprite Renderer’s “sprite” property

Terrain.cs helper class

  • Has public enum TerrainType defined => {Sand, Water, Dirt}

  • Has public class TerrainDefinition for simple mapping of TerrainType and its Sprite

  • Class Terrain contains List which is filled in constructor

The code is below.

Terrain.cs

//  Possible terrain types
public enum TerrainType
{
    Sand,
    Water,
    Dirt
}

// Structure to map terrain type with its corresponding sprite
public class TerrainDefinition
{
    public TerrainType type;
    public Sprite sprite;

    public TerrainDefinition(TerrainType t, Sprite s)
    {
        type = t;
        sprite = s;
    }
}

// Implementation of the type => sprite mapping
// Logic to retrieve a sprite by type and other stuff like getting terrain properties...
public class Terrain
{
    private List<TerrainDefinition> terrainList = new List<TerrainDefinition>();

    public Terrain()
    {
        terrainList.Add(new TerrainDefinition(
                                              TerrainType.Sand,
                                              Resources.Load<Sprite>("Sprites/Sand")
                                              )
                       );

        terrainList.Add(new TerrainDefinition(
                                              TerrainType.Dirt,
                                              Resources.Load<Sprite>("Sprites/Dirt")
                                              )
                        );
    }

    public Sprite GetSpriteByType(TerrainType t)
    {
        for (int i=0; i < terrainList.Count; i++)
        {
            if (terrainList*.type == t)*

{
return terrainList*.sprite;*
}
}

return null;
}
}
Tile.cs
public class Tile : MonoBehaviour
{
public TerrainType terrainType;

public void Start()
{
SetTerrainType(terrainType);
}

public void SetTerrainType(TerrainType t)
{
Terrain trn = new Terrain();
GetComponent().sprite = trn.GetSpriteByType(t);
terrainType = t;
}
}
What I am not happy with is that Terrain data is moved outside the Tile.cs. I think that each Tile should be aware of its possible types and its sprite representation without having to call other classes. The same for handling additional logic like “whether the tile is walkable”, “what speed this tile can be passed” and bla-bla-bla.
The reason I moved the Terrain data outside the Tile.cs is to have only one place where sprites are physically loaded into memory, assuming that I will probably have a lot of tile and each Tile object will have duplicates of sprite images loaded, which is not very good.
My questions are about corret data structure in this case:
1) Should Tile class contain all info about its possible properties and images associated with these properties? Or properties info and logic should be moved outside the Tile class?
2) Storing sprites inside Tile class will lead to duplicating images in the memory for each object? Or it will work like “references” to single memory space?
3) I use Resources.Load to load images and map the with “terrain type”, is this OK? I read that using Unity IDE to set resource references by drag and drop is better way, should I avoid using Resource.Load?
Thanks for answers and happy conding!

Here’s an interesting alternative to making a tile sort of game.
By using a mesh to make voxels.

i dont know but my own preference its store maps like ints or enums arrays fields, where those values represent what you want. like 0 to none, 1 wall, 2 floor , 3 door etc…
i think its a lot easier that way so just parse that data to your map. also you can map minimaps quickly using these values.