个人游戏技术选型案例:输入系统为什么不能只按键盘写死

一个个人动作冒险游戏在旧输入代码、引擎输入系统和自定义映射层之间做技术选型的案例,详细讨论键鼠、手柄、重绑定、教程提示和可访问性。

写在前面:输入系统看起来小,实际会穿透整个游戏

很多个人开发者早期做原型时,都会直接写输入代码。

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 动作是否触发”。

这让输入设备变成可替换细节。

四、为什么上下文很重要

方澈最初以为动作映射就够了。

后来发现,如果没有输入上下文,问题仍然很多。

比如 ConfirmInteract 可能是同一个按键。
在游戏中它表示和路灯互动,在菜单中它表示确认,在对话中它表示下一句。

如果没有上下文,玩家站在 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、教程、设置、可访问性和平台体验。

早期直接读键可以做原型。
但只要游戏准备商业发布,最好尽早把“设备输入”和“游戏动作”分开。

这不是架构洁癖。
这是为了让玩家按下任何一个合理的键时,游戏都能可靠理解他的意图。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页