在 Unity 中获取鼠标和键盘输入,核心依赖 旧版 Input Manager(简单直观)或 新版 Input System(功能强大)。以下是两种系统的具体实现方法,覆盖「键盘按键检测、轴向输入、鼠标位置/按键/滚轮、拖拽」等核心场景,直接复制代码即可使用。

一、旧版 Input Manager(推荐快速开发/简单项目)

无需额外安装,直接通过 Input 类静态 API 调用,适合原型开发或简单交互。

1. 键盘输入(按键检测 + 轴向移动)

(1)单个按键检测(按下/抬起/长按)

using UnityEngine;

public class KeyboardInputDemo : MonoBehaviour
{
    void Update()
    {
        // 1. 按键按下(单次触发,如跳跃、射击)
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Debug.Log("空格键按下(单次触发)");
        }

        // 2. 按键抬起(单次触发)
        if (Input.GetKeyUp(KeyCode.Escape))
        {
            Debug.Log("ESC键抬起(单次触发)");
        }

        // 3. 按键长按(持续触发,如加速)
        if (Input.GetKey(KeyCode.LeftShift))
        {
            Debug.Log("左Shift长按中(持续触发)");
        }

        // 4. 字母/数字键检测
        if (Input.GetKeyDown(KeyCode.A)) Debug.Log("A键按下");
        if (Input.GetKeyDown(KeyCode.1)) Debug.Log("数字1按下");
    }
}

(2)轴向输入(WASD/方向键,适合移动)

Unity 默认配置了 Horizontal(水平)和 Vertical(垂直)轴,直接获取 -1~1 的数值,支持平滑过渡:

public class PlayerMovement : MonoBehaviour
{
    public float moveSpeed = 5f;

    void Update()
    {
        // 水平轴:A/左箭头=-1,D/右箭头=1,无操作=0
        float horizontal = Input.GetAxis("Horizontal");
        // 垂直轴:S/下箭头=-1,W/上箭头=1,无操作=0
        float vertical = Input.GetAxis("Vertical");

        // 计算移动方向(normalized 避免斜向移动速度过快)
        Vector3 moveDir = new Vector3(horizontal, 0, vertical).normalized;
        // 平移物体(Time.deltaTime 使移动速度与帧率无关)
        transform.Translate(moveDir * moveSpeed * Time.deltaTime);
    }
}
  • 平滑 vs 即时:
    • Input.GetAxis("Horizontal"):带渐变(从 0→1 有过渡),适合平滑移动。
    • Input.GetAxisRaw("Horizontal"):无渐变(直接返回 -1/0/1),适合快速响应(如菜单切换)。

2. 鼠标输入(位置/按键/滚轮/拖拽)

(1)鼠标按键检测(左键/右键/中键)

通过索引区分按键:0=左键,1=右键,2=中键

public class MouseInputDemo : MonoBehaviour
{
    void Update()
    {
        // 左键按下(单次触发,如点击交互)
        if (Input.GetMouseButtonDown(0))
        {
            Debug.Log("鼠标左键按下");
        }

        // 右键长按(持续触发,如拖拽)
        if (Input.GetMouseButton(1))
        {
            Debug.Log("鼠标右键长按中");
        }

        // 中键抬起(单次触发,如取消操作)
        if (Input.GetMouseButtonUp(2))
        {
            Debug.Log("鼠标中键抬起");
        }
    }
}

(2)鼠标位置(屏幕坐标)

屏幕坐标原点在 左下角(x=0,y=0),右上角为(x=Screen.width, y=Screen.height):

void Update()
{
    // 获取鼠标屏幕坐标
    Vector3 mouseScreenPos = Input.mousePosition;
    Debug.Log($"鼠标位置:X={mouseScreenPos.x}, Y={mouseScreenPos.y}");

    // 示例:让物体跟随鼠标(2D项目)
    if (Camera.main.orthographic) // 判断是否为2D相机
    {
        // 屏幕坐标 → 世界坐标(2D需设置z轴为0)
        Vector3 mouseWorldPos = Camera.main.ScreenToWorldPoint(mouseScreenPos);
        mouseWorldPos.z = 0; // 2D项目避免z轴偏移
        transform.position = mouseWorldPos;
    }
}

(3)鼠标滚轮(缩放/滚动)

通过 Input.mouseScrollDelta.y 获取滚动量(向上=正值,向下=负值):

public class MouseScrollDemo : MonoBehaviour
{
    public float scaleSpeed = 0.1f;
    public Vector3 minScale = new Vector3(0.5f, 0.5f, 0.5f); // 最小缩放
    public Vector3 maxScale = new Vector3(2f, 2f, 2f); // 最大缩放

    void Update()
    {
        // 获取滚轮滚动量(y轴为垂直滚动,x轴为水平滚动(部分鼠标支持))
        float scroll = Input.mouseScrollDelta.y;

        // 缩放物体
        transform.localScale += new Vector3(scroll * scaleSpeed, scroll * scaleSpeed, scroll * scaleSpeed);
        // 限制缩放范围(避免过大/过小)
        transform.localScale = Vector3.ClampMagnitude(transform.localScale, maxScale.magnitude);
        transform.localScale = Vector3.Max(transform.localScale, minScale);
    }
}

(4)鼠标拖拽(世界空间,需 Collider)

物体必须有 Collider(如 BoxCollider)才能响应鼠标点击,通过「按下+位置变化」实现拖拽:

public class MouseDragDemo : MonoBehaviour
{
    private bool isDragging = false;
    private Vector3 offset; // 鼠标与物体的偏移(避免瞬移)

    // 鼠标点击物体时触发(需 Collider)
    void OnMouseDown()
    {
        // 射线检测:将鼠标屏幕坐标转换为世界射线
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out RaycastHit hit))
        {
            // 计算物体中心与射线命中点的偏移
            offset = transform.position - hit.point;
            isDragging = true;
        }
    }

    // 鼠标抬起时结束拖拽
    void OnMouseUp()
    {
        isDragging = false;
    }

    void Update()
    {
        if (isDragging)
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out RaycastHit hit))
            {
                // 保持偏移,平滑拖拽
                transform.position = hit.point + offset;
            }
        }
    }
}

二、新版 Input System(推荐复杂项目/多平台)

功能更强(支持多设备、按键重映射、自定义输入),需先安装包,适合复杂交互或多平台项目。

1. 前期配置(3步)

  1. 安装包:Window → Package Manager → 搜索 Input System → 安装(安装后重启 Unity)。
  2. 创建输入资源:右键 Project 窗口 → Input Actions → 命名(如 PlayerInputActions)。
  3. 配置输入映射(双击打开配置窗口):
    • 新建 Action Map(如 Player)。
    • 添加 Action 并绑定按键(示例):
      Action 名称 类型 绑定内容
      Move Value→Vector2 WASD + 方向键(Keyboard/W/A/S/D + Arrow Keys)
      Jump Button 空格键(Keyboard/Space)
      LeftClick Button 鼠标左键(Mouse/Left Button)
      MousePos Value→Vector2 鼠标位置(Mouse/Position)
      MouseScroll Value→Vector2 鼠标滚轮(Mouse/Scroll)

2. 代码中使用(回调/实时读取)

(1)键盘输入(移动 + 跳跃)

通过回调函数响应输入,更灵活:

using UnityEngine;
using UnityEngine.InputSystem;

public class NewInputKeyboardDemo : MonoBehaviour
{
    private PlayerInputActions inputActions;
    public float moveSpeed = 5f;

    void Awake()
    {
        // 初始化输入资源
        inputActions = new PlayerInputActions();

        // 绑定跳跃回调(按下时触发)
        inputActions.Player.Jump.performed += OnJump;

        // 绑定移动回调(持续触发,输入变化时调用)
        inputActions.Player.Move.performed += OnMove;
        inputActions.Player.Move.canceled += OnMoveCanceled; // 移动停止时触发
    }

    // 跳跃逻辑
    void OnJump(InputAction.CallbackContext context)
    {
        Debug.Log("跳跃触发(新版Input)");
        GetComponent<Rigidbody>().AddForce(Vector3.up * 5f, ForceMode.Impulse);
    }

    // 移动逻辑
    void OnMove(InputAction.CallbackContext context)
    {
        // 读取移动输入(Vector2:x=水平,y=垂直)
        Vector2 moveInput = context.ReadValue<Vector2>();
        Vector3 moveDir = new Vector3(moveInput.x, 0, moveInput.y).normalized;
        transform.Translate(moveDir * moveSpeed * Time.deltaTime);
    }

    // 移动停止时的逻辑
    void OnMoveCanceled(InputAction.CallbackContext context)
    {
        Debug.Log("移动停止");
    }

    // 启用/禁用输入(避免后台触发)
    void OnEnable() => inputActions.Enable();
    void OnDisable() => inputActions.Disable();
}

(2)鼠标输入(位置/点击/滚轮)

using UnityEngine;
using UnityEngine.InputSystem;

public class NewInputMouseDemo : MonoBehaviour
{
    private PlayerInputActions inputActions;

    void Awake()
    {
        inputActions = new PlayerInputActions();

        // 鼠标左键点击回调
        inputActions.Player.LeftClick.performed += ctx => Debug.Log("鼠标左键点击(新版Input)");

        // 鼠标滚轮回调
        inputActions.Player.MouseScroll.performed += ctx =>
        {
            Vector2 scroll = ctx.ReadValue<Vector2>();
            Debug.Log($"滚轮滚动:Y={scroll.y}");
            // 缩放逻辑(同旧版)
            transform.localScale += new Vector3(scroll.y * 0.1f, scroll.y * 0.1f, scroll.y * 0.1f);
        };
    }

    void Update()
    {
        // 实时读取鼠标位置(屏幕坐标)
        Vector2 mousePos = inputActions.Player.MousePos.ReadValue<Vector2>();
        Debug.Log($"鼠标位置(新版):X={mousePos.x}, Y={mousePos.y}");
    }

    void OnEnable() => inputActions.Enable();
    void OnDisable() => inputActions.Disable();
}

三、关键注意事项(避坑指南)

  1. 物体不响应鼠标事件?

    • 必须给物体添加 Collider(如 BoxCollider、SphereCollider),且 Is Trigger 未勾选(或勾选后用 OnTrigger 事件)。
    • 确保相机是「MainCamera」(或代码中指定正确相机,如 Camera.main 替换为自定义相机引用)。
  2. 坐标转换问题(屏幕→世界)

    • 3D 项目:必须用 Camera.ScreenPointToRay(射线检测)获取世界坐标,不能直接用 ScreenToWorldPoint(会忽略深度)。
    • 2D 项目:ScreenToWorldPoint 需手动设置 z 轴(如 mouseWorldPos.z = 0),否则物体可能消失。
  3. 输入延迟/不流畅?

    • 旧版:Input.GetAxis 有平滑过渡,如需即时响应改用 Input.GetAxisRaw
    • 新版:Action 类型选择「Button」(单次触发)或「Value」(持续输入),避免回调逻辑过重。
  4. 多按键冲突?

    • Input.GetKeyDown 时,避免同时检测多个按键(如 AD 同时按下),可通过 Input.GetAxis 自动处理(返回 0)。

总结

场景 推荐方案 核心优势
快速原型/简单交互 旧版 Input Manager 无需配置,代码简洁
复杂项目/多平台 新版 Input System 支持重映射、多设备,扩展性强
移动类输入(WASD) 轴向输入(GetAxis) 平滑过渡,避免斜向速度过快
鼠标拖拽/点击 Collider + 射线检测 精准响应物体交互

根据项目复杂度选择输入系统,核心逻辑可直接复用上述代码,如需扩展(如自定义按键、多设备支持),可进一步配置 Input 系统的参数。