写在前面:输入系统看起来小,实际会穿透整个游戏
很多个人开发者早期做原型时,都会直接写输入代码。
按 WASD 移动。
按空格跳跃。
按鼠标左键攻击。
按 E 互动。
这样做原型很快。
但等游戏开始支持手柄、改键、教程提示、菜单导航、Steam Deck 或无障碍设置时,早期写死的输入会变成项目里最难清理的部分之一。
方澈做过一款俯视角动作冒险游戏。
玩家控制一名送灯人,在雾气很重的山路上点亮路灯、躲避影子、用灯油维持安全区域。
游戏最早只面向键鼠。
Demo 之后,玩家反馈集中在两个点:
- 很适合手柄,但手柄支持不好
- 键位不能改,左手玩家很难受
方澈这时才意识到,输入系统不是“上线前补一下”的功能。
他最后没有继续在各个脚本里加判断,而是做了一层统一输入映射。
这个选择让后续手柄、键鼠提示和重绑定都变得可控。
一、旧方案的问题在哪里
早期代码很直观。
角色移动脚本里读取方向键。
战斗脚本里读取攻击键。
交互脚本里读取 E。
菜单里读取鼠标点击和方向键。
这种写法在原型阶段没问题。
问题是,当输入需求变多时,每个系统都开始知道太多细节:
- 角色脚本知道键盘和手柄
- UI 脚本知道确认键和取消键
- 教程文本写死了“按 E”
- 暂停菜单和游戏内输入互相冲突
- 手柄断开后状态没有统一处理
- 键位重绑定要改很多地方
最麻烦的是教程提示。
玩家用键盘时应该显示 E。
用 Xbox 手柄时应该显示 A。
用 PlayStation 手柄时应该显示叉号。
玩家改键后,提示也要跟着变。
如果输入散落在各个脚本里,这件事会非常痛苦。
二、三个可选方案
方澈列了三个方案。
第一个方案是继续修补旧代码。
优点是短期最快,缺点是越修越散,后期每个新系统都要重复处理键鼠和手柄。
第二个方案是完全依赖引擎输入系统。
Unity 的新 Input System 或 Godot 的 Input Map 都能处理多设备和动作映射。优点是成熟,缺点是游戏内重绑定、教程图标和上下文切换仍然需要自己组织。
第三个方案是在引擎输入系统之上再封一层游戏动作层。
底层负责读取设备,游戏只关心“移动”“攻击”“互动”“取消”“打开背包”这些动作。
他最后选第三个。
不是因为它最复杂,而是因为它把输入细节挡在了玩法系统之外。
三、动作层如何设计
方澈把输入分成三层。
第一层是设备层:
- Keyboard
- Mouse
- Gamepad
- Steam Deck
第二层是动作层:
- Move
- Aim
- Attack
- Dash
- Interact
- UseLantern
- OpenMap
- Confirm
- Cancel
第三层是上下文:
- Gameplay
- Dialogue
- Menu
- Rebinding
- Cutscene
游戏代码只订阅动作。
角色控制器不再问“空格有没有按下”,而是问“Dash 动作是否触发”。
交互系统不再问“E 键有没有按下”,而是问“Interact 动作是否触发”。
这让输入设备变成可替换细节。
四、为什么上下文很重要
方澈最初以为动作映射就够了。
后来发现,如果没有输入上下文,问题仍然很多。
比如 Confirm 和 Interact 可能是同一个按键。
在游戏中它表示和路灯互动,在菜单中它表示确认,在对话中它表示下一句。
如果没有上下文,玩家站在 NPC 旁边打开菜单时,很容易同时触发游戏内互动和菜单确认。
所以他做了一个简单的上下文栈。
正常游玩时是 Gameplay。
打开菜单时压入 Menu。
进入改键界面时压入 Rebinding。
关闭后弹出,回到之前状态。
同一个动作在不同上下文里有不同含义。
同时,低优先级上下文不会收到输入。
这套设计不复杂,但能解决大量边界问题。
五、按键重绑定不是只保存一个键
很多人以为重绑定就是把 Interact = E 改成 Interact = F。
实际要处理更多细节:
- 同一个动作可能有键盘和手柄两套绑定
- 一个动作可能有主绑定和备用绑定
- 某些按键不能绑定,比如 Esc 或系统键
- 绑定冲突时要提示
- 恢复默认设置要可靠
- 本地化文本和图标要同步
- 存档或配置文件要记录玩家设置
方澈把输入配置单独存成一个用户配置文件,不放进游戏存档。
理由是:
玩家可能删除存档重新开始,但输入偏好应该保留。
同一台机器上不同存档,也应该共享输入设置。
这个细节很小,但体验更合理。
六、教程提示从文本改成 token
旧教程写的是:
“按 E 点亮路灯。”
新方案改成:
“按 {Interact} 点亮路灯。”
显示时,UI 根据当前设备和玩家绑定,把 {Interact} 替换成对应图标或文字。
如果玩家切换到手柄,提示自动变。
如果玩家把互动改到 F,提示也跟着变。
这让教程、提示、设置界面和键位配置共用同一套数据。
个人游戏里很多 UI bug 都来自信息源不一致。
输入提示尤其如此。
七、手柄支持要真实测试
方澈接入手柄后,没有只用自己手上的一个 Xbox 手柄测试。
他至少测试了:
- Xbox 手柄
- PlayStation 手柄
- Switch Pro 手柄
- Steam Deck
- 手柄断开和重连
- 同时插键鼠和手柄
他发现几个问题:
- 不同手柄确认键习惯不同
- Steam Input 可能改变设备识别
- 手柄断开时角色可能保留上一次方向
- UI 焦点在鼠标和手柄之间切换会丢失
- 图标包需要覆盖常见布局
这些问题如果等发售后才发现,会非常影响评价。
手柄支持不是“能动”就结束。
它要覆盖菜单、暂停、教程、弹窗、设置和退出流程。
八、最终取舍
方澈没有做特别复杂的输入框架。
最终方案是:
- 底层使用引擎输入系统
- 游戏层只暴露动作
- UI 和教程使用动作 token
- 输入上下文用栈管理
- 用户配置和存档分离
- 支持键鼠和常见手柄
- 暂不支持复杂组合键和宏
这个方案足够支撑第一版。
他没有为了未来可能的多人合作,提前设计多玩家输入路由。
也没有做完整无障碍按键方案,只先保证重绑定、图标和设备切换可靠。
这是个人项目应有的克制。
结语:输入系统越早抽象,后面越少返工
方澈后来回看,输入系统重构花了 9 天。
如果等正式版内容接近完成再做,可能要花一个月,还会引入更多 bug。
个人游戏技术选型里,输入系统很容易被低估。
它连接玩法、UI、教程、设置、可访问性和平台体验。
早期直接读键可以做原型。
但只要游戏准备商业发布,最好尽早把“设备输入”和“游戏动作”分开。
这不是架构洁癖。
这是为了让玩家按下任何一个合理的键时,游戏都能可靠理解他的意图。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。