You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 04:57:36