尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Unity基础:Input输入系统入门——键盘、鼠标与触摸检测

Unity基础:Input输入系统入门——键盘、鼠标与触摸检测 Unity基础Input输入系统入门——键盘、鼠标与触摸检测大家好欢迎回到Unity教程系列。前面几篇文章我们学了写脚本、调试代码但真正让游戏具有交互性的是输入。玩家按下键盘、点击鼠标、滑动屏幕——这些操作如何被Unity检测到并传递给游戏逻辑就是今天这篇文章要讲的内容。Unity的输入系统有两套旧版Input ManagerUnity默认和新版Input System需要安装Package。对初学者来说先从旧版入手是最快的新版Input System我会在后续进阶章节中详细讲解。一、Unity输入系统概述1.1 输入管理的本质 游戏输入系统的核心任务很简单检测用户的物理操作按键、点击、触摸、摇杆并将其转化为游戏可以使用的数据。Unity的Input Manager帮我们完成了底层的所有繁重工作——它已经知道键盘上每个按键的编号、鼠标的运动增量、触摸屏的多点触控信息。你不需要关心操作系统层面的输入细节只需要调用Unity提供的Input API。1.2 Input Manager的配置打开Edit Project Settings Input Manager你会看到大量的输入轴Axes定义。默认配置包含Horizontal水平轴←→方向键 和 A/D键Vertical垂直轴↑↓方向键 和 W/S键Fire1、Fire2、Fire3开火键左Ctrl/鼠标左键、左Alt/鼠标右键、左Shift/鼠标中键Jump跳跃空格键Mouse X / Mouse Y鼠标移动Mouse ScrollWheel鼠标滚轮你可以在这里添加自定义的输入轴给特定的按键或摇杆映射一个有意义的名称。二、键盘输入检测2.1 Input.GetKey —— 持续检测Input.GetKey(KeyCode key)在按住指定键的每一帧都返回true。适合用于持续性的操作voidUpdate(){// 按住W键持续向前移动if(Input.GetKey(KeyCode.W)){transform.Translate(Vector3.forward*speed*Time.deltaTime);}// 按住Shift键加速跑if(Input.GetKey(KeyCode.LeftShift)){currentSpeedrunSpeed;}else{currentSpeedwalkSpeed;}}2.2 Input.GetKeyDown —— 按下瞬间Input.GetKeyDown(KeyCode key)只在按键被按下的那一帧返回true。适合触发一次性动作voidUpdate(){// 按空格键跳跃只触发一次if(Input.GetKeyDown(KeyCode.Space)){Jump();}// 按R键重新装弹if(Input.GetKeyDown(KeyCode.R)){Reload();}// 按Escape键打开/关闭菜单if(Input.GetKeyDown(KeyCode.Escape)){TogglePauseMenu();}}2.3 Input.GetKeyUp —— 松开瞬间Input.GetKeyUp(KeyCode key)在按键被松开的那一帧返回truevoidUpdate(){// 松开Shift键时停止冲刺if(Input.GetKeyUp(KeyCode.LeftShift)){StopSprinting();}// 松开鼠标按键时停止蓄力if(Input.GetKeyUp(KeyCode.Mouse0)){ReleaseChargedAttack();}}2.4 常用KeyCode枚举// 字母键KeyCode.A 到 KeyCode.Z// 数字键KeyCode.Alpha0 到 KeyCode.Alpha9 KeyCode.Keypad0 到 KeyCode.Keypad9// 小键盘数字// 功能键KeyCode.Space// 空格KeyCode.Return// 回车KeyCode.Escape// EscKeyCode.Tab// TabKeyCode.Backspace// 退格KeyCode.Delete// Delete// 方向键KeyCode.UpArrow/KeyCode.DownArrow KeyCode.LeftArrow/KeyCode.RightArrow// 修饰键KeyCode.LeftShift/KeyCode.RightShift KeyCode.LeftControl/KeyCode.RightControl KeyCode.LeftAlt/KeyCode.RightAlt// 鼠标KeyCode.Mouse0// 鼠标左键KeyCode.Mouse1// 鼠标右键KeyCode.Mouse2// 鼠标中键// 功能键F1-F12KeyCode.F1 到 KeyCode.F122.5 Input.anyKeyDown —— 任意键voidUpdate(){// 检测是否按下了任意键用于按任意键开始if(Input.anyKeyDown){StartGame();}}三、轴输入Axes Input3.1 Input.GetAxis —— 平滑轴值Input.GetAxis(string axisName)返回一个-1到1之间的平滑浮点值。这是Unity输入系统中使用最广泛的API。voidUpdate(){// 获取水平轴←→方向键或A/D键floathorizontalInput.GetAxis(Horizontal);// 获取垂直轴↑↓方向键或W/S键floatverticalInput.GetAxis(Vertical);// 组合成移动向量Vector3movementnewVector3(horizontal,0,vertical);transform.Translate(movement*speed*Time.deltaTime);}GetAxis的特点值是平滑过渡的。按键瞬间值不会立即从0跳到1而是有一个渐变过程类似加速度。这让角色移动、镜头旋转等操作手感更加自然。3.2 Input.GetAxisRaw —— 原始轴值Input.GetAxisRaw(string axisName)与GetAxis的区别在于它没有平滑过渡值直接是-1、0或1。// 用于需要即时响应的场景如2D格斗游戏的左右移动floatrawHorizontalInput.GetAxisRaw(Horizontal);// rawHorizontal 的值只可能是 -1, 0, 或 1没有过渡值3.3 默认输入轴轴名称正方向键负方向键描述Horizontal→ / D← / A水平移动Vertical↑ / W↓ / S垂直移动Mouse X鼠标右移鼠标左移鼠标水平移动增量Mouse Y鼠标上移鼠标下移鼠标垂直移动增量Mouse ScrollWheel向上滚动向下滚动鼠标滚轮Fire1左Ctrl / 鼠标左键-主开火键Fire2左Alt / 鼠标右键-副开火键Fire3左Shift / 鼠标中键-第三开火键Jump空格键-跳跃3.4 自定义输入轴在Input Manager中点击一个轴的名称旁边的三角形展开详细设置Name轴的名称代码中调用的字符串Descriptive Name描述性名称Negative Button / Positive Button负方向和正方向对应的按键Alt Negative / Alt Positive备选按键Gravity按键松开后值回弹到0的速度Sensitivity按键按下后值变化到1或-1的速度Snap勾选后按下反向键时值立即归零Dead Zone死区摇杆用小幅度偏移被忽略四、鼠标输入检测4.1 鼠标按键检测voidUpdate(){// 检测鼠标按键和键盘按键检测方式一样使用KeyCode.Mouse0/1/2if(Input.GetKeyDown(KeyCode.Mouse0)){Debug.Log(鼠标左键按下);}if(Input.GetKey(KeyCode.Mouse1)){Debug.Log(鼠标右键按住中);}// 也可以使用Button名称if(Input.GetButtonDown(Fire1)){Debug.Log(Fire1按下等同于鼠标左键或左Ctrl);}}4.2 鼠标位置voidUpdate(){// 获取鼠标在屏幕上的像素坐标左下角为原点Vector3mouseScreenPosInput.mousePosition;// 从屏幕坐标生成射线3D场景中的鼠标拾取RayrayCamera.main.ScreenPointToRay(Input.mousePosition);if(Physics.Raycast(ray,outRaycastHithit)){Debug.Log($鼠标指向了{hit.collider.gameObject.name});}}4.3 鼠标移动增量voidUpdate(){// 获取鼠标本帧的移动增量floatmouseXInput.GetAxis(Mouse X);floatmouseYInput.GetAxis(Mouse Y);// 使用鼠标增量旋转视角FPS游戏的标准做法transform.Rotate(Vector3.up*mouseX*mouseSensitivity);cameraTransform.Rotate(Vector3.left*mouseY*mouseSensitivity);}⚠️ 注意Mouse X和Mouse Y返回的是本帧的移动增量而不是绝对坐标。这是为了处理FPS游戏中的鼠标旋转FPS游戏通常不关心鼠标的绝对位置只关心它移动了多少。4.4 鼠标滚轮voidUpdate(){floatscrollInput.GetAxis(Mouse ScrollWheel);if(scroll!0){// 滚轮向上为正向下为负// 典型用途缩放相机Camera.main.fieldOfView-scroll*zoomSpeed;Camera.main.fieldOfViewMathf.Clamp(Camera.main.fieldOfView,15f,90f);}}4.5 光标管理// 隐藏并锁定光标FPS游戏标准做法Cursor.lockStateCursorLockMode.Locked;Cursor.visiblefalse;// 限制光标在窗口内但不隐藏Cursor.lockStateCursorLockMode.Confined;// 恢复正常光标Cursor.lockStateCursorLockMode.None;Cursor.visibletrue;五、移动端触摸检测5.1 多点触控基础voidUpdate(){// 检测当前帧的触摸点数量if(Input.touchCount0){// 获取第一个触摸点TouchtouchInput.GetTouch(0);switch(touch.phase){caseTouchPhase.Began:Debug.Log($手指按下位置{touch.position});break;caseTouchPhase.Moved:Debug.Log($手指移动位置{touch.position}增量{touch.deltaPosition});break;caseTouchPhase.Stationary:// 手指没动但还按着break;caseTouchPhase.Ended:Debug.Log(手指抬起);break;caseTouchPhase.Canceled:Debug.Log(触摸被系统中断如来电);break;}}}5.2 遍历所有触摸点voidUpdate(){for(inti0;iInput.touchCount;i){TouchtouchInput.GetTouch(i);// fingerId是触摸点的唯一标识同一根手指的整个触摸周期不变Debug.Log($手指{touch.fingerId}{touch.phase}位置{touch.position});}}5.3 Touch结构体的属性属性类型描述fingerIdint手指标识同一手指不变positionVector2当前触摸位置屏幕像素坐标deltaPositionVector2自上一帧的位置变化deltaTimefloat自上一帧的时间间隔tapCountint连击次数phaseTouchPhase触摸阶段Began/Moved/Stationary/Ended/Canceledpressurefloat按压力度支持3D Touch的设备radiusfloat触摸区域的估算半径5.4 移动端输入适配// 同时支持键盘、鼠标和触摸的移动控制voidUpdate(){Vector3movementVector3.zero;// PC端键盘#ifUNITY_STANDALONE || UNITY_EDITORmovement.xInput.GetAxis(Horizontal);movement.zInput.GetAxis(Vertical);#endif// 移动端触摸虚拟摇杆或滑动#ifUNITY_IOS || UNITY_ANDROIDif(Input.touchCount0){TouchtouchInput.GetTouch(0);// 简易滑动控制movement.xtouch.deltaPosition.x*touchSensitivity;movement.ztouch.deltaPosition.y*touchSensitivity;}#endiftransform.Translate(movement*speed*Time.deltaTime);}六、Input Button——更抽象的输入层6.1 GetButton / GetButtonDown / GetButtonUp除了直接检测按键Unity还提供了一层更抽象的输入Button。Button通过名称来引用具体的按键映射在Input Manager中配置。voidUpdate(){// 使用Button名称更灵活可以在InputManager中重新映射按键if(Input.GetButtonDown(Jump)){Jump();}if(Input.GetButton(Fire1)){// 持续开火按住连发}if(Input.GetButtonUp(Fire2)){// 松开副开火键}} 使用Button而不是直接检测KeyCode的好处是玩家可以在游戏设置中重新映射按键你的代码不需要修改——只需要在Input Manager中更改Button的映射即可。七、完整的角色控制器示例usingUnityEngine;publicclassCharacterController:MonoBehaviour{[Header(移动设置)]publicfloatwalkSpeed5f;publicfloatrunSpeed10f;publicfloatjumpForce8f;[Header(视角设置)]publicfloatmouseSensitivity2f;publicfloatmaxLookAngle80f;privateRigidbodyrb;privateCameraplayerCamera;privatefloatverticalLookRotation;privateboolisGrounded;voidStart(){rbGetComponentRigidbody();playerCameraGetComponentInChildrenCamera();// FPS游戏标准光标设置Cursor.lockStateCursorLockMode.Locked;Cursor.visiblefalse;}voidUpdate(){// --- 鼠标视角控制 ---floatmouseXInput.GetAxis(Mouse X)*mouseSensitivity;floatmouseYInput.GetAxis(Mouse Y)*mouseSensitivity;// 水平旋转角色整体旋转transform.Rotate(Vector3.up*mouseX);// 垂直旋转只旋转相机限制角度verticalLookRotation-mouseY;verticalLookRotationMathf.Clamp(verticalLookRotation,-maxLookAngle,maxLookAngle);playerCamera.transform.localRotationQuaternion.Euler(verticalLookRotation,0,0);// --- 移动 ---floathorizontalInput.GetAxis(Horizontal);floatverticalInput.GetAxis(Vertical);Vector3movementtransform.right*horizontaltransform.forward*vertical;floatcurrentSpeedInput.GetKey(KeyCode.LeftShift)?runSpeed:walkSpeed;movement*currentSpeed;// 保持Y轴速度重力影响movement.yrb.velocity.y;rb.velocitymovement;// --- 跳跃 ---if(Input.GetButtonDown(Jump)isGrounded){rb.AddForce(Vector3.up*jumpForce,ForceMode.Impulse);}// --- 其他操作 ---if(Input.GetKeyDown(KeyCode.E)){Interact();}if(Input.GetKeyDown(KeyCode.Escape)){Cursor.lockStateCursorLockMode.None;Cursor.visibletrue;}}voidInteract(){// 交互逻辑}}八、本篇总结✅ 本文核心知识点回顾Input.GetKey检测键盘持续按下GetKeyDown检测按下瞬间GetKeyUp检测松开瞬间Input.GetAxis返回平滑过渡的轴值-1到1GetAxisRaw返回离散值-1/0/1Input.mousePosition获取鼠标屏幕坐标Mouse X/Y获取移动增量Input.GetTouch获取移动端触摸信息支持多点触控Cursor.lockState管理光标隐藏和锁定使用Button名称而非直接检测KeyCode方便后期重新映射按键 下一篇文章将深入讲解Time.deltaTime——让物体移动与帧率无关的核心概念。动手任务① 用Input.GetKey实现WASD移动空格跳跃② 用Input.GetAxis和Mouse X/Y实现FPS视角旋转③ 在移动设备上测试触摸检测关于作者拥有多年Unity开发经验的游戏开发者专注Unity系统化教学与最佳实践分享。
返回列表