Multiple Hex placement grid

Hello, Noob here. I have a 2d project where I want to create a hex grid for unit placement. Currently I have a script that creates a hex mesh and then uses that mesh to create a hex grid.

I also implemented a mouse over color change. Which worked great. Then I switched it from reacting to the mouse pointer to reacting to a single hex I moved with the mouse. Again, worked great.

But what I really want is for it to react to multiple hexes, as the units will have varying sizes. Smallest unit may be 1 hex but a larger unit might take 3 or 7 hexes of space. At my current level of Unity noobness I can’t figure out how to do this, nor the best way to go about it.

Currently I am applying a script to each individual grid hex that checks for a raycast and changes the color. This was based on an example I found to do the mouse over.

My idea was to create a group of ‘selection hexes’ that matched the size of the unit and as I move it around it would highlight a legitimate location to place it (i.e. unit size 7 finds 7 empty hexes). No idea if this is the way to go about it and currently what I have doesn’t work anyway. I just took my working single example and put it in a loop. But, again, it doesn’t work, it just highlights 1 hex at a time.

Any advice on how to best implement this? Best practices?

Code attached to hexes in the grid:

using UnityEngine;

[RequireComponent(typeof(Collider))]
public class GridHex : MonoBehaviour {
	Color normalColor;
	GameObject[] selectors;
    //public Transform selectionObject;

    void Awake() {
		selectors = GameObject.FindGameObjectsWithTag("selectortile");
        //selectionObject = GameObject.Find("HexagonSelectorTile").transform;
    }

	void Start() {
		normalColor = GetComponent<Renderer>().material.color;
	}

	void Update () {
		foreach (GameObject selector in selectors) {
			//Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
			//Ray ray = new Ray(selectionObject.position, Vector3.forward);
			Ray ray = new Ray(selector.transform.position, Vector3.forward);
			RaycastHit hitInfo;
	
			Debug.DrawRay(ray.origin, ray.direction, Color.green);
			if (GetComponent<Collider>().Raycast(ray, out hitInfo, Mathf.Infinity)) {
				GetComponent<Renderer>().material.color = UnityEngine.Color.red;
			} else {
				GetComponent<Renderer>().material.color = normalColor;
			}			
		}
	}
}

What it looks like:
55200-hex.png

I see what you are trying to do and I may be able to help. There is a formula you can use that, when the width and length of the tile is entered, can calculate a world coordinate, into a hex based coordinate, and back again if you wished. I have actually built a method to do so, but it is slightly confusing just to enter into here. I am going to suggest you use the initial coordinate to find the hexs around it. The offset you need would be on the y, .75*height, and for the x, it would be width\2 every other tile.

Well I got this working, but I think it’s pretty ugly. I’m not sure I’m passing data back & forth in a good way. And I’m not happy using OnMouseOver & OnMouseExit. I tried some OnCollision events but couldn’t make them work.

Anyway, there’s a lot going on, but it boils down to this. In a Grid class I have:

    public List<GridTile> GetAdjacentTiles(Vector2 pPosition) {
        int x = (int)pPosition.x;
        int y = (int)pPosition.y;
        int w = gridWidthInHexes - 1;
        int h = gridHeightInHexes - 1;

       List<GridTile> Adjacents = new List<GridTile>();
       
       if (x > 0) {
            Adjacents.Add(hexes[x-1,y].GetComponent<GridTile>());
        }
        if (x < w) {
            Adjacents.Add(hexes[x+1,y].GetComponent<GridTile>());
        }
        if (y > 0) {  //the two above
            if (y % 2 == 0) { //even row
                Adjacents.Add(hexes[x, y - 1].GetComponent<GridTile>());
                if (x != 0) Adjacents.Add(hexes[x - 1,y - 1].GetComponent<GridTile>());
            } else { //odd rows
                Adjacents.Add(hexes[x,y - 1].GetComponent<GridTile>());
                if (x < w) Adjacents.Add(hexes[x + 1,y - 1].GetComponent<GridTile>());
            }
        }
        if (y < h) {  //the two below
            if (y % 2 == 0) { //even row
                Adjacents.Add(hexes[x, y + 1].GetComponent<GridTile>());
                if (x != 0) Adjacents.Add(hexes[x - 1,y + 1].GetComponent<GridTile>());
            } else { //odd rows
                Adjacents.Add(hexes[x,y + 1].GetComponent<GridTile>());
                if (x < w) Adjacents.Add(hexes[x + 1,y + 1].GetComponent<GridTile>());
            }            
        }          
        return Adjacents;
    }

And In a Tile class I have:

	void OnMouseOver() {
		this.IsSelected = true;
		
		List<GridTile> adjecentTiles = gridMap.GetAdjacentTiles(myGridPosition);
		
		foreach (GridTile gt in adjecentTiles) {
			gt.IsSelected = true;
			gt.SetVisual();
		}
	}
	void OnMouseExit() {
		this.IsSelected = false;
		
		List<GridTile> adjecentTiles = gridMap.GetAdjacentTiles(myGridPosition);
		
		foreach (GridTile gt in adjecentTiles) {
			gt.IsSelected = false;
			gt.SetVisual();
		}		
	}

Which results in this as I move my mouse around: