如何在2D网格上为任意数量点位生成近似box矩形编队
解决方案
一、rows和cols的取值逻辑
核心目标是让编队的宽高比尽可能接近1(最接近正方形),最大程度缩短元素整体移动距离,具体逻辑如下:
- 先取总元素数
count = selection.Count - 计算列数
cols = (int)Math.Ceiling(Math.Sqrt(count)),取总数量的平方根向上取整作为列数 - 计算行数
rows = (int)Math.Ceiling(count * 1.0 / cols),用总数量除以列数向上取整得到行数
可以用示例验证逻辑正确性:
- 总数量为9:
sqrt(9)=3,cols=3,rows=9/3=3,正好3*3的正方形,匹配示例效果 - 总数量为5:
sqrt(5)≈2.236,向上取整得cols=3,rows=Ceiling(5/3)=2,正好2行3列,匹配示例效果
如果你的场景需要优先减少行数/列数,也可以调整为先算行数再算列数,逻辑对称。
二、单个点位新坐标计算
默认约定网格坐标规则:x轴向右递增,y轴向下递增,mousePosition为编队的几何中心位置(也就是示例里x标记的位置),计算逻辑如下:
- 对每个元素的索引
i,先计算它在编队内的行号、列号:- 行号:
rowIdx = i / cols(整数除法,向下取整) - 列号:
colIdx = i % cols
- 行号:
- 计算相对于中心原点的偏移量:
- 列偏移:
offsetX = colIdx - (cols - 1) / 2(让编队中间列对齐原点的x坐标) - 行偏移:
offsetY = rowIdx - (rows - 1) / 2(让编队中间行对齐原点的y坐标,若行数为偶数,编队整体向下偏移半格,符合示例效果)
- 列偏移:
- 最终坐标为原点加偏移:
new Vector2Int(origin.x + offsetX, origin.y + offsetY)
三、完整代码示例
//selection是网格上的随机位置列表,点击地图后需要让选中的点位移动形成box矩形编队 Vector2Int origin = mousePosition; List<Vector2Int> boxPositions = new List<Vector2Int>(); int count = selection.Count; // 计算行列数 int cols = (int)Math.Ceiling(Math.Sqrt(count)); int rows = (int)Math.Ceiling((double)count / cols); for (int i = 0; i < count; i++) { int rowIdx = i / cols; int colIdx = i % cols; int offsetX = colIdx - (cols - 1) / 2; int offsetY = rowIdx - (rows - 1) / 2; Vector2Int myNewlyCalculatedPosition = new Vector2Int(origin.x + offsetX, origin.y + offsetY); boxPositions.Add(myNewlyCalculatedPosition); }
内容的提问来源于stack exchange,提问作者Majs
相关产品推荐
相关产品推荐

