在 Unity 中,鼠标和键盘操作是交互开发的核心,主要通过 Input 系统 实现(包括旧版 Input Manager 和新版 Input System)。以下是详细的操作方法、常用 API 和实战示例,覆盖大部分场景:

一、核心概念:两种 Input 系统

Unity 提供两种输入系统,根据项目需求选择:

特性 旧版 Input Manager(默认) 新版 Input System(推荐)
易用性 简单直观,无需额外安装 功能强大,支持多设备、重映射
兼容性 全平台支持,无需配置 需要安装包(Package Manager)
代码复杂度 低(静态 API 调用) 中等(需配置 Input Action)
适用场景 快速原型、简单项目 复杂交互、多平台项目(PC/主机/移动)

切换 Input 系统

  1. 新版 Input System 需先在 Package Manager 中安装 Input System 包。
  2. 安装后会提示切换输入系统,选择 Yes(重启 Unity 生效)。

二、旧版 Input Manager(快速上手)

适合快速开发,直接通过 Input 类静态方法获取输入,无需额外配置。

1. 键盘操作

(1)基础按键检测(按下/抬起/长按)

功能 API 示例 说明
按键按下(单次触发) Input.GetKeyDown(KeyCode.Space) 按键按下的第一帧返回 true(如跳跃)
按键抬起(单次触发) Input.GetKeyUp(KeyCode.Space) 按键抬起的第一帧返回 true
按键长按(持续触发) Input.GetKey(KeyCode.W) 按键按住期间每帧返回 true(如移动)

(2)常用 KeyCode 枚举(键盘按键)

  • 方向键:KeyCode.UpArrowKeyCode.DownArrowKeyCode.LeftArrowKeyCode.RightArrow
  • 字母数字:KeyCode.AKeyCode.1KeyCode.Zero
  • 功能键:KeyCode.Space(空格)、KeyCode.Escape(ESC)、KeyCode.LeftShift(左Shift)
  • 特殊键:KeyCode.Return(回车)、KeyCode.Tab(Tab)、KeyCode.Backspace(退格)

(3)轴向输入(如 WASD/方向键移动)

Unity 默认配置了 轴向输入(无需额外设置),直接获取 -1~1 之间的数值,适合平滑移动:

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

// 平滑移动示例(绑定到 Transform)
Vector3 moveDir = new Vector3(horizontal, 0, vertical).normalized;
transform.Translate(moveDir * speed * Time.deltaTime);
  • Input.GetAxis("Horizontal"):带平滑过渡(从 0 渐变到 ±1),适合移动。
  • Input.GetAxisRaw("Horizontal"):无平滑(直接返回 -1/0/1),适合快速响应(如菜单切换)。

2. 鼠标操作

(1)鼠标按键检测

功能 API 示例 说明
左键按下 Input.GetMouseButtonDown(0) 0=左键,1=右键,2=中键(滚轮按下)
左键抬起 Input.GetMouseButtonUp(0) 单次触发
左键长按 Input.GetMouseButton(0) 持续触发

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

  • 屏幕坐标原点:左下角(x=0, y=0),右上角(x=Screen.width, y=Screen.height)。
  • API:Vector3 mousePos = Input.mousePosition;
    // 示例:获取鼠标在屏幕中央的偏移
    float offsetX = Input.mousePosition.x - Screen.width / 2;
    float offsetY = Input.mousePosition.y - Screen.height / 2;
    

(3)鼠标滚轮(滚动量)

  • API:float scroll = Input.mouseScrollDelta.y;
    • 向上滚动:返回正值(默认 1)
    • 向下滚动:返回负值(默认 -1)
    • 示例(缩放物体):
      float scroll = Input.mouseScrollDelta.y;
      transform.localScale += new Vector3(scroll * 0.1f, scroll * 0.1f, scroll * 0.1f);
      transform.localScale = Vector3.Max(transform.localScale, new Vector3(0.5f, 0.5f, 0.5f)); // 限制最小缩放
      

(4)鼠标拖拽(屏幕空间)

通过检测鼠标按下 + 鼠标位置变化实现拖拽:

private bool isDragging = false;
private Vector3 offset; // 鼠标与物体的偏移(避免物体瞬移到鼠标位置)

void OnMouseDown() // 鼠标点击物体时触发(需物体有 Collider)
{
    // 计算鼠标世界坐标与物体中心的偏移
    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; // 保持偏移,平滑拖拽
        }
    }
}
  • 注意:物体必须有 Collider(如 BoxCollider),OnMouseDown 才会触发。

三、新版 Input System(推荐,功能更强)

新版 Input System 支持多设备、按键重映射、自定义输入行为,适合复杂项目。以下是核心用法:

1. 前期配置

  1. 安装 Input System 包(Package Manager → 搜索 Input System → 安装)。
  2. 创建 Input Action 资源:右键 Project 窗口 → Input Actions → 命名(如 PlayerInputActions)。
  3. 双击打开配置窗口,添加输入映射(示例:移动、跳跃、鼠标拖拽):
    • 新建 Action Map(如 Player)。
    • 添加 Action(如 Move,类型设为 ValueVector2Jump 设为 Button)。
    • 为 Action 绑定按键:
      • Move:绑定 WASD(Keyboard/W/A/S/D)和方向键(Keyboard/Arrow Keys/Up/Down/Left/Right)。
      • Jump:绑定 Space(Keyboard/Space)。
      • MouseDrag:绑定 Left Button(Mouse/Left Button)。

2. 代码中使用(C#)

(1)基础输入检测(通过回调)

using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerController : MonoBehaviour
{
    private PlayerInputActions inputActions;

    void Awake()
    {
        // 初始化 Input Action
        inputActions = new PlayerInputActions();

        // 绑定按键回调(Jump 按下时触发)
        inputActions.Player.Jump.performed += OnJumpPerformed;
        // 绑定移动轴向输入(持续回调)
        inputActions.Player.Move.performed += OnMovePerformed;
        inputActions.Player.Move.canceled += OnMoveCanceled; // 移动停止时触发
    }

    void OnJumpPerformed(InputAction.CallbackContext context)
    {
        Debug.Log("跳跃触发!");
        // 跳跃逻辑(如添加向上的力)
        GetComponent<Rigidbody>().AddForce(Vector3.up * 5f, ForceMode.Impulse);
    }

    void OnMovePerformed(InputAction.CallbackContext context)
    {
        Vector2 moveInput = context.ReadValue<Vector2>(); // 获取 WASD/方向键输入(x=-1~1, y=-1~1)
        Vector3 moveDir = new Vector3(moveInput.x, 0, moveInput.y).normalized;
        transform.Translate(moveDir * 3f * Time.deltaTime);
    }

    void OnMoveCanceled(InputAction.CallbackContext context)
    {
        // 移动停止时的逻辑(如减速)
    }

    void OnEnable()
    {
        inputActions.Enable(); // 启用输入
    }

    void OnDisable()
    {
        inputActions.Disable(); // 禁用输入(避免后台触发)
    }
}

(2)鼠标操作(新版 Input System)

绑定鼠标相关 Action 后,通过 ReadValue 获取输入:

// 1. 配置 Input Action:
// - 添加 Action `MousePosition`(类型 Value → Vector2),绑定 Mouse/Position。
// - 添加 Action `MouseScroll`(类型 Value → Vector2),绑定 Mouse/Scroll。
// - 添加 Action `LeftClick`(类型 Button),绑定 Mouse/Left Button。

// 2. 代码中读取:
void Awake()
{
    inputActions = new PlayerInputActions();
    // 鼠标点击回调
    inputActions.Player.LeftClick.performed += ctx => Debug.Log("鼠标左键点击!");
    // 鼠标滚轮回调
    inputActions.Player.MouseScroll.performed += ctx => 
    {
        Vector2 scroll = ctx.ReadValue<Vector2>();
        Debug.Log("滚轮滚动:" + scroll.y);
    };
}

void Update()
{
    // 实时获取鼠标位置(屏幕坐标)
    Vector2 mousePos = inputActions.Player.MousePosition.ReadValue<Vector2>();
    Debug.Log("鼠标位置:" + mousePos);
}

(3)鼠标拖拽(世界空间,新版)

private bool isDragging = false;
private Vector3 offset;

void Awake()
{
    inputActions = new PlayerInputActions();
    // 鼠标按下时开始拖拽
    inputActions.Player.LeftClick.performed += ctx => StartDrag();
    // 鼠标抬起时结束拖拽
    inputActions.Player.LeftClick.canceled += ctx => isDragging = false;
}

void StartDrag()
{
    Ray ray = Camera.main.ScreenPointToRay(inputActions.Player.MousePosition.ReadValue<Vector2>());
    if (Physics.Raycast(ray, out RaycastHit hit) && hit.collider.gameObject == gameObject)
    {
        offset = transform.position - hit.point;
        isDragging = true;
    }
}

void Update()
{
    if (isDragging)
    {
        Ray ray = Camera.main.ScreenPointToRay(inputActions.Player.MousePosition.ReadValue<Vector2>());
        if (Physics.Raycast(ray, out RaycastHit hit))
        {
            transform.position = hit.point + offset;
        }
    }
}

四、常见问题与注意事项

  1. 物体不响应鼠标事件

    • 确保物体有 Collider(如 BoxColliderSphereCollider),且 Is Trigger 未勾选(或勾选后用 OnTrigger 事件)。
    • 确保相机是 MainCamera(或代码中指定正确的相机)。
  2. 轴向输入无响应

    • 旧版:检查 Edit → Project Settings → Input Manager → Axes 中是否有 HorizontalVertical 轴(默认存在)。
    • 新版:检查 Input Action 中是否正确绑定了按键,且代码中启用了 inputActions
  3. 鼠标位置转换问题

    • 屏幕坐标 → 世界坐标:必须用 Camera.ScreenPointToRay(2D 用 Camera.ScreenToWorldPoint,需设置 z 轴距离)。
    • 示例(2D 鼠标位置转换):
      Vector3 mouseScreenPos = new Vector3(inputActions.Player.MousePosition.ReadValue<Vector2>().x, 
                                           inputActions.Player.MousePosition.ReadValue<Vector2>().y, 
                                           Camera.main.nearClipPlane);
      Vector3 mouseWorldPos = Camera.main.ScreenToWorldPoint(mouseScreenPos);
      mouseWorldPos.z = 0; // 2D 项目中 z 轴设为 0
      
  4. 输入延迟

    • 旧版:Input.GetAxis 有平滑过渡,如需即时响应改用 Input.GetAxisRaw
    • 新版:确保 Action 类型正确(Button 适合单次触发,Value 适合持续输入)。

五、实战示例:PC 端第三人称移动(旧版 Input Manager)

using UnityEngine;

public class ThirdPersonMovement : MonoBehaviour
{
    public float moveSpeed = 5f;
    public float rotateSpeed = 10f;
    private Rigidbody rb;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
        rb.freezeRotation = true; // 冻结旋转,避免物理碰撞导致旋转
    }

    void Update()
    {
        // 获取键盘输入
        float horizontal = Input.GetAxisRaw("Horizontal");
        float vertical = Input.GetAxisRaw("Vertical");
        Vector3 moveDir = new Vector3(horizontal, 0, vertical).normalized;

        // 移动
        if (moveDir.magnitude > 0.1f)
        {
            // 旋转朝向移动方向
            Quaternion targetRot = Quaternion.LookRotation(moveDir);
            transform.rotation = Quaternion.Lerp(transform.rotation, targetRot, rotateSpeed * Time.deltaTime);
            // 平移
            rb.MovePosition(transform.position + moveDir * moveSpeed * Time.deltaTime);
        }

        // 鼠标滚轮缩放相机
        float scroll = Input.mouseScrollDelta.y;
        Camera.main.fieldOfView = Mathf.Clamp(Camera.main.fieldOfView - scroll * 2f, 40f, 80f);
    }
}

总结

  • 简单项目/原型:用旧版 Input Manager,代码简洁,无需配置。
  • 复杂项目/多平台:用新版 Input System,支持重映射、多设备,扩展性更强。
  • 核心要点:鼠标操作需结合 Collider 和射线检测,键盘操作优先使用轴向输入(平滑移动),按键检测区分“单次触发”(GetKeyDown)和“持续触发”(GetKey)。

根据项目需求选择合适的输入系统,配合 Collider、射线检测等功能,可实现绝大多数 PC 端交互逻辑。