5-12 笔刷尺寸
在上一章中,我们将修改地图单元的高度和颜色这两个功能,通过选中与取消选中的方式进行了分离。现在可以只对地图单元进行高度编辑,或者只进行颜色编辑。现在,随着地图尺寸的增加,我们只对单个的地图单元修改,就显得非常繁琐,效率也很低。在本章中,我们来创建一个“笔刷”功能,使用户可以调整笔刷尺寸,来批量对地图单元进行修改。
与高度滑动条类似,我们再创建一个笔刷尺寸滑动条,如下图:
在HexMapEditor.cs
中,添加一个方法来读取笔刷尺寸滑动条的数值,代码如下:
1 | public class HexMapEditor : MonoBehaviour |
代码完成后,回到Unity中,将笔刷尺寸滚动条的最小值设置为0,最大值设置为4,并绑定SetBrushSize
方法,如下图:
接下来,我们需要创建一个方法,这个方法用来调用笔刷半径内所有地图单元的EditCell
方法。其中鼠标选中的地图单元为笔刷的中心。代码如下:
1 | private void HandleInput() |
我们定义了笔刷尺寸的最大值和最小值,当笔刷半径为0时,就只修改鼠标当前选中的地图单元。当半径为1时,包含当前选中的地图单元和跟选中地图单元相邻的地图单元。当半径为2时,包含中心地图单元、与中心地图单元相邻的所有地图单元、以及与中心地图单元相邻地图单元外侧相邻的地图单元。如笔刷范围示意图所示,此图下方代码也要用到:
要编辑这些地图单元的高度或者颜色,我们在知道笔刷半径的情况下,就需要循环遍历笔刷覆盖的所有地图单元。那么首先就需要获取笔刷中心地图单元的坐标。这里我们可以直接使用HexCoordinates
结构体中转换好的坐标。代码如下:
1 | private void EditCells(HexCell center) |
获取到笔刷中心地图单元的坐标后,我们需要根据这个坐标和笔刷半径,来确定其余在笔刷范围内的地图单元。这里我们先从Z坐标开始,并且将之分为两个部分,先从最底部一行开始遍历,一直遍历到笔刷中心地图单元所在的行为止。代码如下:
1 | private void EditCells(HexCell center) |
通过观察笔刷范围示意图我们可以发现,在笔刷覆盖范围内的下半部分中,最底部一行的第一个地图单元,永远和中心地图单元有相同的X坐标值。并且行数越接近中心行,每行第一个地图单元的X坐标值就越小。每一行的最后一个地图单元,其X坐标值都等于笔刷中心地图单元的X坐标值加上笔刷半径。根据这两个规律,我们就可以遍历得到每一行中在笔刷范围内的地图单元的X坐标了。代码如下:
1 | private void EditCells(HexCell center) |
这里要注意,我们目前并没有hexGrid.GetCell(HexCoordinates coordinates)
这个重载,所以需要在HexGrid.cs
中创建这个重载方法。目的是通过地图中的一组坐标值,来获取到对应坐标值的地图单元实例。代码如下:
1 | public class HexGrid : MonoBehaviour |
至此,我们就可以修改一半笔刷范围内的地图单元了,如下图:
接下来,我们只需要参考之前的逻辑,将循环进行对称,也就是从最顶端一行开始遍历,一直到除了中间行之外的上半部分所有的地图单元。代码如下:
1 | private void EditCells(HexCell center) |
现在笔刷范围虽然完整了,但是当我们对地图进行修改的时候,如果笔刷范围延伸到地图边界之外时,就会报一个数组越界的错误。为了避免这个错误,我们在HexGrid.GetCell(HexCoordinates coordinates)
方法中检测边界,并且当获取到不存在的地图单元时返回null。代码如下:
1 | public HexCell GetCell(HexCoordinates coordinates) |
并且为了防止空引用异常,在HexMapEditor.EditCell(HexCell cell)
方法中要检查被编辑的地图单元是否有实例存在。代码如下:
1 | private void EditCell(HexCell cell) |
至此,我们就完成了笔刷的基本功能,我们可以自定义笔刷大小,来批量修改地图单元的颜色或者高度,这样效率就会高很多,对用户也非常友好。在下一章中,我们将完成目前地图编辑器的最后一部分:显示和隐藏坐标值UI。