在上一章中,我们完成了河流编辑器的UI部分,通过点选Toggle
就可以选择当前是否可以编辑河流。在这一章中,我们继续为创建河流做前期的一些工作,首先是通过什么样的交互形式来创建河流。这里我们通过参考其他的地图编辑器功能,选择了使用鼠标拖动的形式来创建河流。也就是拖动鼠标经过若干个地图单元,地图系统就会跟着鼠标的轨迹在这些地图单元上创建河流。
要实现这个功能,就需要同时获得地图单元的位置和鼠标在这个地图单元移动的方位,回到HexMapEditor.cs
中,在脚本中添加获取这两个数据的方法。代码如下:
HexMapEditor.cs1 2 3 4 5 6 7 8 9 10 11 12 13
| public class HexMapEditor : MonoBehaviour { … private bool isDrag;
private HexDirection dragDirection;
private HexCell previousCell; }
|
最初的时候是没有拖拽事件的,也就没有上一个地图单元的记录。所以当没有输入信息或者没有与地图交互时,需要设置其为null。代码如下:
HexMapEditor.cs1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| public class HexMapEditor : MonoBehaviour { …
private void Update() { if (Input.GetMouseButtonUp(0) && !EventSystem.current.IsPointerOverGameObject()) { HandleInput(); } else { previousCell = null; } }
private void HandleInput() { …
if (Physics.Raycast(_inputRay, out _hit)) { … } else { previousCell = null; } } }
|
当前地图单元是根据射线碰撞点找到的,当在这一帧里结束编辑时,它就会变成下一次Update里的上一个地图单元。代码如下:
HexMapEditor.cs1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class HexMapEditor : MonoBehaviour { …
private void HandleInput() { …
if (Physics.Raycast(_inputRay, out _hit)) { HexCell currentCell = hexGrid.GetCell(_hit.point); EditCells(currentCell); previousCell = currentCell; } else { … } } }
|
确认了当前射线碰撞到的地图单元之后,我们可以与前一个地图单元(如果有的话)进行比较,当发现是两个不同的单元格时,就说明可能存在有效拖动并需要去检测,要不就是没有拖拽事件。代码如下:
HexMapEditor.cs1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public class HexMapEditor : MonoBehaviour { …
private void HandleInput() { …
if (Physics.Raycast(_inputRay, out _hit)) { HexCell currentCell = hexGrid.GetCell(_hit.point);
if (previousCell && previousCell != currentCell) { ValidateDrag(currentCell); } else { isDrag = false; }
… } else { … } } }
|
如何证实确实是拖拽事件?通过检测当前地图单元是否与前一个地图单元相邻,循环遍历前一个地图单元所有相邻地图单元来进行检测,如果找到了与当前地图单元相吻合的结果,就能同时确认拖拽的方向。代码如下:
HexMapEditor.cs1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public class HexMapEditor : MonoBehaviour { … private void ValidateDrag(HexCell currentCell) { for (dragDirection = HexDirection.NE; dragDirection <= HexDirection.NW; dragDirection++) { if (previousCell.GetNeighbor(dragDirection) == currentCell) { isDrag = true; return; } } isDrag = false; } }
|
这样逐帧检测这不会产生拖拽抖动么?
当你移动鼠标穿过地图单元边界时,可能会在单元格之间快速来回摆动,这确实会导致拖拽抖动,但情况没那么糟。
可以通过记录上一次拖拽事件来减缓抖动,然后防止下一次直接向相反方向拖拽即可。
至此,我们完成了通过检测鼠标左键按下后,是否产生了拖拽的动作。在下一章中,我们将继续完善移除和添加河流的部分代码,并最终可以在Inspector的Debug模式下看到效果。
Github代码