Unity游戏光标平滑移动异常求助:Input Actions使用问题
问题:Unity Input Actions 光标平滑移动异常
我用Input Actions实现游戏光标移动,加Time.DeltaTime做平滑移动时,光标会在松开输入前就提前停住;但去掉Time.DeltaTime后,移动正常却变成瞬移,不符合需求。
*编辑:已修改代码,Y轴高度调整功能正常,但平滑移动问题仍未解决,调整调用条件也没用,求解决建议。
public class cursor : MonoBehaviour { [SerializeField] float speed = 1f; public float height; RaycastHit hit; [SerializeField] LayerMask terrainLayerMask; [SerializeField] LayerMask obstacleLayer; void Update() { Ray ray = new Ray (transform.position, -Vector3.up); Debug.DrawRay(transform.position, Vector3.down * height, Color.yellow); if (Physics.Raycast(ray, out hit)) { if(hit.collider.tag == "terrain") { Debug.Log(hit.point.y); var position = transform.position; position.y = hit.point.y +3.5f; transform.position = position; } } } public void OnCursorLeft(InputAction.CallbackContext context) { if (context.performed == true) { var position = transform.position; position.z += 2; transform.position = position; if(transform.position.z > 32) { position.z = 32; transform.position = position; } } } public void OnCursorRight(InputAction.CallbackContext context) { if (context.performed == true) { var position = transform.position; position.z -= 2; transform.position = position; position.y = hit.point.y +3.5f; if(transform.position.z <= 0) { position.z = 0; transform.position = position; } } } public void OnCursorUp(InputAction.CallbackContext context) { if (context.performed == true) { var position = transform.position; position.x += 2; transform.position = position; if(transform.position.x > 32) { position.x = 32; transform.position = position; } } } public void OnCursorDown(InputAction.CallbackContext context) { if (context.performed == true) { var position = transform.position; position.x -= 2; transform.position = position; if(transform.position.x <= 0) { position.x = 0; transform.position = position; } } } }
解决思路及修改方案
核心问题是你用performed回调处理持续移动——Input Action的performed仅在输入触发时(比如按键按下瞬间)触发一次,或按设备采样频率间断触发,无法像Update帧检测那样持续响应输入。加Time.DeltaTime会因触发次数不足导致移动提前终止,不加就变成每次跳固定距离的瞬移。
正确实现方式
改用InputAction.ReadValue<Vector2>()在Update中读取输入轴的持续值,每一帧获取输入状态,配合Time.DeltaTime实现平滑连贯的移动。
修改后的代码示例
using UnityEngine; using UnityEngine.InputSystem; public class Cursor : MonoBehaviour { [SerializeField] float moveSpeed = 10f; [SerializeField] float heightOffset = 3.5f; [SerializeField] LayerMask terrainLayerMask; private PlayerInput playerInput; private InputAction moveAction; void Awake() { playerInput = GetComponent<PlayerInput>(); moveAction = playerInput.actions["CursorMove"]; // 对应你设置的移动Input Action名称 } void Update() { // 处理Y轴贴合地形 Ray ray = new Ray(transform.position, -Vector3.up); Debug.DrawRay(transform.position, Vector3.down * 10f, Color.yellow); if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity, terrainLayerMask)) { Vector3 newPos = transform.position; newPos.y = hit.point.y + heightOffset; transform.position = newPos; } // 平滑移动+边界限制 Vector2 inputDir = moveAction.ReadValue<Vector2>(); Vector3 moveVector = new Vector3(inputDir.x, 0, inputDir.y) * moveSpeed * Time.deltaTime; Vector3 targetPos = transform.position + moveVector; targetPos.x = Mathf.Clamp(targetPos.x, 0, 32); targetPos.z = Mathf.Clamp(targetPos.z, 0, 32); transform.position = targetPos; } }
关键修改点
- 放弃
performed回调,改用Update帧内读取输入轴持续值,保证输入响应的连贯性,配合Time.DeltaTime实现平滑移动。 - 用
Mathf.Clamp简化边界限制逻辑,避免重复设置transform.position。 - 优化射线检测参数,延长射线长度避免地形检测漏判。
- 规范类名和变量命名,提升代码可读性。
额外注意事项
- 确保你的Input Action设置为
Vector2类型,绑定方向键/WASD时选择Digital Normalized或Analog模式,以获取连续输入值。 - 若坚持用回调方式,可监听
started/performed/canceled状态,在started标记输入开始、canceled标记结束,再在Update中根据标记处理移动,但这种方式不如直接读取值简洁。
内容的提问来源于stack exchange,提问作者NectarNoks
相关产品推荐
相关产品推荐

