Unity:如何实现按住键盘让GameObject单次移动1单位且避免重复移动?
解决Unity方向键按住时角色重复移动的问题
我正在制作一款解谜平台游戏,主角通过方向键上下左右移动。点击方向键时移动正常,但想实现按住方向键持续移动、抬手即停的效果。当前使用的代码如下:
void Update() { if (Input.GetKey(KeyCode.DownArrow)) { direction = 2; } if (Input.GetKey(KeyCode.LeftArrow)) { direction = 3; } if (Input.GetKey(KeyCode.UpArrow)) { direction = 4; } if (Input.GetKey(KeyCode.RightArrow)) { direction = 1; } if (Input.GetKeyUp(KeyCode.DownArrow) || Input.GetKeyUp(KeyCode.LeftArrow) || Input.GetKeyUp(KeyCode.UpArrow) || Input.GetKeyUp(KeyCode.RightArrow)) { direction = 0; } movePacman(); } private void movePacman() { switch (direction) { case 1: moveRight(); break; case 2: moveDown(); break; case 3: moveLeft(); break; case 4: moveUp(); break; default: break; } }
目前遇到的问题:若不快速松开按键,角色有时会连续移动两次,请问该如何解决?
问题原因
原代码中Update每帧都会调用movePacman,如果moveRight/moveLeft等方法是瞬间移动一格(直接修改位置到目标格子),按住按键时每帧执行一次移动会导致速度过快,且松开按键时可能因输入帧的延迟,最后一帧仍执行了移动操作,出现“连续移动两次”的错觉。
解决方案
方案1:计时器控制格子移动间隔(适合吃豆人式逐格移动)
添加计时器变量,固定每间隔一段时间才移动一次,避免每帧重复触发:
private float moveTimer; public float moveInterval = 0.2f; // 移动间隔,值越小移动越快 void Update() { // 优先处理方向输入 if (Input.GetKey(KeyCode.DownArrow)) { direction = 2; } else if (Input.GetKey(KeyCode.LeftArrow)) { direction = 3; } else if (Input.GetKey(KeyCode.UpArrow)) { direction = 4; } else if (Input.GetKey(KeyCode.RightArrow)) { direction = 1; } else { // 无按键按住时重置方向和计时器 direction = 0; moveTimer = 0; return; } // 累加计时器,达到间隔才移动 moveTimer += Time.deltaTime; if (moveTimer >= moveInterval) { movePacman(); moveTimer = 0; // 重置计时器 } } private void movePacman() { switch (direction) { case 1: moveRight(); break; case 2: moveDown(); break; case 3: moveLeft(); break; case 4: moveUp(); break; default: break; } }
方案2:改为平滑持续移动(适合平台跳跃式平滑位移)
如果你的角色需要平滑移动而非逐格跳跃,修改move系列方法,用Time.deltaTime控制移动速度,同时简化输入逻辑:
首先修改移动方法:
public float moveSpeed = 5f; // 调整移动速度 private void moveRight() { transform.Translate(Vector2.right * moveSpeed * Time.deltaTime); } private void moveLeft() { transform.Translate(Vector2.left * moveSpeed * Time.deltaTime); } private void moveUp() { transform.Translate(Vector2.up * moveSpeed * Time.deltaTime); } private void moveDown() { transform.Translate(Vector2.down * moveSpeed * Time.deltaTime); }
然后简化Update逻辑:
void Update() { direction = 0; // 默认无方向 if (Input.GetKey(KeyCode.DownArrow)) { direction = 2; } else if (Input.GetKey(KeyCode.LeftArrow)) { direction = 3; } else if (Input.GetKey(KeyCode.UpArrow)) { direction = 4; } else if (Input.GetKey(KeyCode.RightArrow)) { direction = 1; } movePacman(); }
内容的提问来源于stack exchange,提问作者Tal Angel
相关产品推荐
相关产品推荐

