How to get an object to know what objects are connected to it (tile based game)

(unity 3d) I’m trying to generate hexagonal shapes and I’m trying to make each hexagon know any other hexagons it’s touching (this is because it’s a tile based game, and would make development much easier). Currently I’m trying raycasting, but am having troubles. I’ve also never used raycasting. So if anyone knows either a better way to do this or how to fix this raycasting that would be appreciated

(These scripts are very bulky, currently just trying to get something that works then I can shorten them)

vv Tile Generation Script vv

[Header("Tile Prefab")]
public GameObject tile; //the generated tiles have a mesh collider with convex on

[Header("Tile Vars")] // this order is important, mainly for lists but also for other things
public GameObject topRight;
public GameObject right;
public GameObject bottomRight;
public GameObject bottomLeft;
public GameObject left;
public GameObject topLeft;

public GameObject tileSpawnedFrom;
//Length & Height
public float length;
public float height;

private void Start() 
{
        length = GetComponent<MeshFilter>().mesh.bounds.extents.x * gameObject.transform.localScale.x * 2; //geting the hexagons length
        height = (GetComponent<MeshFilter>().mesh.bounds.extents.z * gameObject.transform.localScale.z * 2) / (4f / 3f); //getting the hexagons height
}
[...]
//these get called when a button presses down
    public void SpawnTopRight()
    {
        InstantiateTile(transform.position.x + (length / 2), transform.position.z + height, 0, 3, topRight);
        gameManager.RaycastAllTiles();
    }

    public void SpawnRight()
    {
        InstantiateTile(transform.position.x + length, transform.position.z, 1, 4, right);
        gameManager.RaycastAllTiles();
    }
    public void SpawnBottomRight()
    {
        InstantiateTile(transform.position.x + (length / 2), transform.position.z - height, 2, 5, bottomRight);
        gameManager.RaycastAllTiles();
    }
    public void SpawnBottomLeft()
    {
        InstantiateTile(transform.position.x - (length / 2), transform.position.z - height, 3, 0, bottomLeft);
        gameManager.RaycastAllTiles();
    }
    public void SpawnLeft()
    {
        InstantiateTile(transform.position.x - length, transform.position.z, 4, 1, left);
        gameManager.RaycastAllTiles();
    }
    public void SpawnTopLeft()
    {
       InstantiateTile(transform.position.x - (length/2), transform.position.z + height, 5, 2, topLeft);
        gameManager.RaycastAllTiles(); 
    }

//spawning the tile
    public void InstantiateTile(float xPos, float zPos, int listSpot, int newObjListSpot, GameObject connectedTile)
    {
        if (connectedTile == null)
        {
            GameObject tileObj = Instantiate(tile, Vector3.zero, transform.rotation);
            Vector3 spawningPos = new(xPos, transform.position.y, zPos);
            TileGeneration tileObjScript = tileObj.GetComponent<TileGeneration>();
            tileObj.transform.position = spawningPos;
            tileObj.transform.parent = transform.parent;
            tileObjScript.tileUi = tileUi;
            tileObjScript.tile = tile;
            gameManager.allTiles.Add(tileObj);
        }
        else
            Debug.Log("ERROR, tile already spawned");
    }

^^ Tile Generation Script ^^

vv GameManager Script vv

public List<GameObject> allTiles;
RaycastHit hit;
[...]
    public void RaycastAllTiles()
    {
        Debug.Log("RAYCASTING ALL TILES");
        for (int i = 0; i < allTiles.Count; i++)
        {
            Debug.Log(allTiles[i]);
            TileGeneration tileScript = allTiles[i].GetComponent<TileGeneration>();
            if (Physics.Raycast(transform.position, new(transform.position.x + tileScript.length / 2, transform.position.y, transform.position.z + tileScript.height), out hit, Mathf.Infinity))
            {
                tileScript.topRight = hit.transform.gameObject;
                Debug.Log("COLLIDED");
            } else
            {
                tileScript.topRight = null;
                Debug.Log("DID NOT COLLIDE");
            }
            if (Physics.Raycast(transform.position, Vector3.right, out hit, Mathf.Infinity))
            {
                tileScript.right = hit.transform.gameObject;
                Debug.Log("COLLIDED");
            } else
            {
                tileScript.right = null;
                Debug.Log("DID NOT COLLIDE");
            }

            if (Physics.Raycast(transform.position, new(transform.position.x + tileScript.length / 2, transform.position.y, transform.position.z - tileScript.height), out hit, Mathf.Infinity))
            {
                tileScript.bottomRight = hit.transform.gameObject;
                Debug.Log("COLLIDED");
            } else
            {
                tileScript.bottomRight = null;
                Debug.Log("DID NOT COLLIDE");
            }

            if (Physics.Raycast(transform.position, new(transform.position.x - tileScript.length / 2, transform.position.y, transform.position.z - tileScript.height), out hit, Mathf.Infinity))
            {
                tileScript.bottomLeft = hit.transform.gameObject;
                Debug.Log("COLLIDED");
            } else
            {
                tileScript.bottomLeft = null;
                Debug.Log("DID NOT COLLIDE");
            }

            if (Physics.Raycast(transform.position, new(transform.position.x - tileScript.length, transform.position.y, transform.position.z), out hit, Mathf.Infinity))
            {
                tileScript.left = hit.transform.gameObject;
                Debug.Log("COLLIDED");
            } else
            {
                tileScript.left = null;
                Debug.Log("DID NOT COLLIDE");
            }

            if (Physics.Raycast(transform.position, new(transform.position.x - tileScript.length / 2, transform.position.y, transform.position.z + tileScript.height), out hit, Mathf.Infinity))
            {
                tileScript.topLeft = hit.transform.gameObject;
                Debug.Log("COLLIDED");

            } else
            {
                tileScript.topLeft = null;
                Debug.Log("DID NOT COLLIDE");
            }
        }
    }

If you need more info, ask : )

I’m not sure what it is you’re doing but there’s a couple of possible issues. If a tile’s collider is 2D then a raycast from the side won’t hit it.

And when you instantiate a tile at vector3.zero and then immediately move it elsewhere the physics engine won’t be immediately updated on this move and so the raycast will fail. So instead instantiate the tile at the correct position.

If it is tiled, DO NOT use physics or raycasting: Track the tiles yourself in some kind of data structure, do all your logic there.

YES, you can use physics / raycasting but it’s a complete nightmare of additional complexity.

Here’s a bunch of relevant reading:

Tile-based / grid-based 2D games: match3, tetris, chips challenge, rogue, etc:

For any tile-based game such as Match3 or Tetris or a grid-based Roguelike, do all the logical comparisons in your own data storage mechanism for the tiles, such as a 2D array of tiles.

Otherwise you needlessly bind your game logic into Unity objects and the Unity API, making it about 10x more complicated than it needs to be.

If you have no idea how to work with 2D arrays, hurry to some basic C# tutorials for the language portions of it, then look at any good tutorial that uses a 2D array

Here is my Match3 demo using this technique of storing data in a grid. Full source linked in game comments.

It stores all of its data in a 2D array:

PieceController[,] Board;

This allows for easy simple checking in code, not relying on anything like physics.

You should strive to use that pattern for all logic, then only use Unity to present what is happening in the game logic.

Laying items out in a grid:

Hexagonal maps (hexmaps):

Thanks!, took a bit bit of googling but I eventually got it working (https://www.youtube.com/watch?v=WJimYq2Tczc)