1-9 改变选中地图单元的颜色
在上一章中,我们通过坐标转换,可以知道鼠标点击在了哪一个地图单元上。接下来,我们在这个基础上改变被鼠标点击的地图单元的颜色。
在HexGrid.cs
中声明两个变量,分别为默认颜色和点击后变化的颜色,代码如下:
1 | //cell的默认颜色 |
回到Unity中,选中Hex Grid物体,在Inspector面板中就能看到下图的效果,当然,我们也可以自定义初始颜色和点击后的颜色,如下图:
回到HexCell.cs
中,在这里我们声明一个变量,用来存储每个地图单元自己的颜色。代码如下:
1 | public class HexCell : MonoBehaviour |
为每个地图单元赋初始颜色值,可以在HexGrid.CreateCell方法中实现。代码如下:
1 | private void CreateCell(int x, int z, int i) |
当然,我们还需要将颜色的信息赋值给地图单元的Mesh组件,这样才能将颜色显示出来。代码如下:
1 | //存储cell每个顶点的颜色信息 |
接着,在进行每个三角面片构建的时候,我们将颜色的信息赋值给每一个顶点,这样在构建出地图单元的时候,就带有了我们定义的初始颜色了。代码如下:
1 | public void Triangulate(HexCell[] cells) |
我们回到HexGrid.TouchCell方法中。这个方法的流程可以理解为:先将Unity内普通的坐标,转换成六边形地图中的坐标,即从Unity的Vector3(8.7, 0, 13.9)坐标转换为六边形地图的(0, -1, 1)坐标。
接着,我们还需要知道被点击的地图单元在数组HexGrid.cell[]
中具体的位置,也就是被惦记的地图单元在数组HexGrid.cell[]
中的下标。才可以为该地图单元赋值新的颜色。
如果要改变其颜色,依照现有的方法,我们还需要重新构建整个六边形地图的Mesh,因为这个Mesh是整体存储在一个变量中的。但是我们真的有必要因为某个地图单元的颜色改变而重新构建整个正六边形地图的Mesh吗?答案很显然,重新构建整个Mesh是不合理的。
但是现在还不是优化这个步骤的时候,因为随着项目的功能不断增加,代码会变得越来越复杂,Mesh的外观也会变得复杂。所以现在做的任何优化在之后的代码中都会变得没有意义。虽然重新构建整个正六边形地图的Mesh虽然很无脑,但是却十分有效,目前我们先这样为地图单元更改颜色。代码如下:
1 | private void TouchCell(Vector3 position) |
代码完成之后,我们点击某一个地图单元,但是并没有任何的改变,被点击的地图单元也没有改变颜色。这是因为Unity中默认的着色器没有使用顶点颜色。我们需要自己创建一个自定义着色器(Assets/Create/Shader/Standard Surface Shader),并修改其中的代码。其实我们只需要对Unity新建的着色器进行2处很小的改动:1 在输入部分添加颜色信息。2 输出时让反射率与颜色值相乘。而且我们不必关心透明通道,只需要集中在rgb通道即可。代码如下: s
1 | Shader "Custom/HexCell" |
接下来,新建一个材质球,使用我们修改后的shader,并将这个材质球替换掉场景中Hex Mesh物体组件上的材质球。最后效果如下图:
这里要注意,某些情况下,点击地图单元后,可能会产生一些奇怪的阴影效果!这是因为在某些Unity版本中Standard Surface Shader可能会有阴影问题。如果发生了阴影抖动或者带状阴影的问题,这说明Z轴发生了冲突。调整全局方向光的阴影偏斜角度应该可以解决这个问题。
这样我们就完成了基本的交互功能了。当我们点击一个地图单元后,这个地图单元就会变成我们预先定义好的被点击的颜色。下一章中我们在这个基础上更进一步,制作一个简单的地图编辑器功能,可以为不同的地图单元赋值不同的颜色。