如何在四方向(上下左右)2D游戏中实现基于网格的移动?
搞定2D四方向网格移动的解决方案
嘿,我来帮你解决这个网格移动的问题!先看看你当前代码里的几个核心问题,再一步步调整到符合网格移动的逻辑:
原代码的问题点
- 用了
else if+GetKey:GetKey会持续触发,导致角色平滑滑动而不是“按一次动一格”;else if虽然不影响四方向,但核心问题是持续输入的逻辑完全不符合网格移动的需求 - 没有移动锁定和网格对齐:网格移动需要确保角色精准停在网格节点上,且移动过程中不能重复触发新的移动请求
修改后的完整Player类代码
using UnityEngine; using System.Collections; public class Player : Character { public float moveSpeed = 2f; // 控制移动的平滑速度 public float tileSize = 1f; // 你的网格每个格子的大小,比如1x1就设为1 private bool isMoving = false; // 标记是否正在移动,防止重复触发 /// <summary> /// 重写角色的Update函数,以便执行自定义功能 /// </summary> protected override void Update() { GetInput(); base.Update(); } /// <summary> /// 监听玩家输入,触发网格移动 /// </summary> private void GetInput() { // 如果正在移动,直接跳过输入处理,避免位置错乱 if (isMoving) return; var direction = Vector2.zero; // 用GetKeyDown检测单次按键,实现"按一次动一格"的逻辑 if (Input.GetKeyDown(KeyCode.UpArrow)) { direction = Vector2.up; } else if (Input.GetKeyDown(KeyCode.LeftArrow)) { direction = Vector2.left; } else if (Input.GetKeyDown(KeyCode.DownArrow)) { direction = Vector2.down; } else if (Input.GetKeyDown(KeyCode.RightArrow)) { direction = Vector2.right; } // 有有效输入时启动移动协程 if (direction != Vector2.zero) { StartCoroutine(MoveToTargetTile(direction)); } } /// <summary> /// 协程处理平滑网格移动,确保对齐网格节点 /// </summary> private IEnumerator MoveToTargetTile(Vector2 moveDirection) { isMoving = true; // 计算目标位置:当前位置 + 方向*网格大小,确保落在网格节点上 Vector2 targetPosition = (Vector2)transform.position + moveDirection * tileSize; // 平滑移动到目标位置 while (Vector2.Distance(transform.position, targetPosition) > 0.01f) { transform.position = Vector2.MoveTowards(transform.position, targetPosition, moveSpeed * Time.deltaTime); yield return null; } // 最后强制对齐到目标位置,避免浮点精度误差 transform.position = targetPosition; isMoving = false; } }
关键逻辑说明
- 移动锁定(isMoving):确保角色在移动过程中不会响应新的输入,避免出现一次按键触发多次移动、位置偏移的问题
- 单次输入检测(GetKeyDown):只在按键按下的第一帧触发移动,完美匹配网格移动“按一次动一格”的交互逻辑
- 网格对齐计算:通过
tileSize控制每个格子的大小,目标位置直接基于当前网格节点计算,确保角色始终停在网格上 - 平滑移动协程:用协程实现平滑的移动动画,如果想要即时瞬移(无动画),可以去掉循环部分,直接设置
transform.position = targetPosition
额外优化建议
- 障碍物检测:在启动协程前,添加碰撞检测(比如
Physics2D.OverlapCircle)检查目标位置是否有障碍物,有则取消移动 - 八方向支持:如果后续要扩展八方向,只需要把
else if改成单独的if,允许同时检测两个方向键(比如上+右) - 输入配置化:把方向键改成Unity的Input System轴输入,方便后续支持手柄、自定义按键
内容的提问来源于stack exchange,提问作者Neizhel
相关产品推荐
相关产品推荐

