I think this is a pretty complex problem. I can suggest a solution that will at least partially get you there.
What you can do is loop through the positions as usual, but then transform the coordinates using a matrix. The matrix uses floating points while the grid doesn’t, so there is a bit of manual intervention to eliminate some of the issues. It still doesn’t get you exactly where you want to be but it’s a start.
What we’ll do is process the grid as if we are just using standard ‘up/down’ positions, but then we’ll rotate those positions by 45 degrees. The direction is up to you.
I made a test action to test this and show the result
public override List<GridPosition> GetValidActionGridPositions()
{
// square root of 2 is a unit square's diagonal. this is the inverse to eliminate further division
var sqrt2i = 1f / Mathf.Sqrt(2f);
var width = 6; // test value
var halfWidth = Mathf.RoundToInt(width / 2f); // this is to go left and right of the unit
var height = 4; // test value
// rotation matrix for a 45 degree rotation
var matrix = Matrix4x4.Rotate(Quaternion.AngleAxis(45f, Vector3.up));
// the usual stuff
var unitPos = _unit.GetGridPosition();
var validGridPositions = new List<GridPosition>();
// loop through the positions
for(var z = 0; z < height; z++)
{
for(var x = -halfWidth; x <= halfWidth; x++)
{
// rotate this position after some manual intervention
var position = new Vector3(x * sqrti, 0f, z * sqrt2i);
var rotated = matrix.MultiplyVector(position);
// create the offset
var offset = new GridPosition(Mathf.RoundToInt(rotated.x), Mathf.RoundToInt(rotated.z));
// create the test position
var testPosition = unitPos + offset;
// if the position is not valid, skip it
if (!LevelGrid.Instance.IsValidGridPosition(testPosition)) continue;
// do other tests here
validGridPositions.Add(testPosition);
}
}
return validGridPositions;
}
The result
Like I said, it doesn’t get you what you want, but it’s a step closer. And maybe some clever math-people can come up with a better solution