Unity中使用Input.GetKeyDown实现玩家两点间切换移动的技术问询
实现Unity玩家双位置切换移动功能
核心需求梳理
- 两个固定目标位置:
firstPosition = new Vector2(0, 0)、secondPosition = new Vector2(0, 5) - 按E键触发位置切换:在第一个位置时按E移动到第二个,反之亦然
- 使用
transform.Translate实现平滑移动
优化后的完整代码
using UnityEngine; public class PlayerPositionSwitch : MonoBehaviour { // 定义两个固定目标位置 [SerializeField] private Vector2 firstPosition = new Vector2(0, 0); [SerializeField] private Vector2 secondPosition = new Vector2(0, 5); // 移动速度 [SerializeField] private float moveSpeed = 2f; // 位置判定阈值(避免浮点精度问题) [SerializeField] private float positionThreshold = 0.01f; private Rigidbody2D rig2d; private Vector2 currentTargetPosition; private bool isMoving = false; private void Awake() { rig2d = GetComponent<Rigidbody2D>(); // 初始化当前目标为初始位置 currentTargetPosition = transform.position; } private void Update() { // 只有不在移动状态时,才响应E键输入 if (!isMoving && Input.GetKeyDown(KeyCode.E)) { SwitchTargetPosition(); isMoving = true; // 移动时关闭刚体模拟,避免物理干扰 if (rig2d != null) { rig2d.simulated = false; } } // 如果处于移动状态,执行移动逻辑 if (isMoving) { MoveToTarget(); } } // 切换目标位置 private void SwitchTargetPosition() { // 判断当前位置接近哪个目标,切换到另一个 if (Vector2.Distance(transform.position, firstPosition) < positionThreshold) { currentTargetPosition = secondPosition; } else if (Vector2.Distance(transform.position, secondPosition) < positionThreshold) { currentTargetPosition = firstPosition; } } // 向目标位置移动 private void MoveToTarget() { // 计算朝向目标的方向向量(归一化) Vector2 direction = (currentTargetPosition - (Vector2)transform.position).normalized; // 使用Translate移动,基于世界空间(避免自身旋转影响) transform.Translate(direction * moveSpeed * Time.deltaTime, Space.World); // 检查是否到达目标位置 if (Vector2.Distance(transform.position, currentTargetPosition) < positionThreshold) { // 强制设置到目标位置,消除误差 transform.position = currentTargetPosition; isMoving = false; // 移动结束后恢复刚体模拟 if (rig2d != null) { rig2d.simulated = true; } } } }
关键优化点说明
- 位置判定阈值:使用
positionThreshold避免浮点精度问题,直接用==判断位置会因为浮点误差导致逻辑失效 - 状态管理:用
isMoving变量控制输入响应,避免移动过程中重复触发切换 - 刚体控制:移动时关闭刚体模拟,防止物理系统干扰移动路径,到达后恢复
- 方向计算:基于世界空间移动,避免玩家自身旋转影响移动方向(如果不需要可以改成
Space.Self) - 模块化拆分:将切换逻辑和移动逻辑拆分为单独方法,代码更易维护
对原有代码的适配说明
如果需要保留原有代码中的stairsOn、inHelecopter等变量逻辑,可以将移动触发条件修改为:
if (!isMoving && stairsOn && Input.GetKeyDown(KeyCode.E)) { SwitchTargetPosition(); isMoving = true; inHelecopter.inHelecopter = true; if (rig2d != null) { rig2d.simulated = false; } }
同时在移动结束时添加stairsOn = false;和inHelecopter.inHelecopter = false;(根据需求调整)
内容的提问来源于stack exchange,提问作者amoke
相关产品推荐
相关产品推荐

