今日速览

  • 设置菜单是“上架隐形门槛”:音量分轨、全屏/窗口切换、按键重绑,是玩家默认你必须支持的三件事;Steam Deck 与手柄玩家尤其敏感。
  • 音量别直接改单个播放器:正确做法是走 AudioServer 音频总线(Master ← Music / SFX / UI),一次调用全局生效。
  • 按键重绑靠 InputMap:动作(action)→ 事件(event)的映射可以在运行时用 action_erase_events + action_add_event 改写。
  • 选项要能记住:用 ConfigFile 存到 user://settings.cfg,启动时读、修改后写,换电脑靠 Steam Cloud 同步。
  • 窗口模式改 DisplayServer:window_set_mode / window_set_size,UI 前提是锚点 + 容器自适应。

核心学习内容

1. 为什么它是“必做项”,而不是“加分项”

玩家进游戏第一件事往往不是玩,而是先打开设置:把 BGM 调小、切成全屏、把手柄键位改成顺手的样子。如果这些没有,轻则差评“没有键位设置”,重则 Steam Deck 上因无法适配输入与显示而拿不到 Verified。所以设置菜单不是锦上添花,而是能上架的最低配置。

2. 音量:走音频总线,一次调用全局生效

Godot 的音频走“总线(Bus)”结构(见官方 Audio buses 文档):最左边是 Master,其余总线向右挂、向左汇流。建议建 Music、SFX、UI 三条子总线汇入 Master。音量单位是分贝(dB)——0 dB 是上限,-6 dB 约等于一半响度,低于 -60 dB 基本听不见。

但 UI 滑块给玩家的通常是 0~1 的线性值,所以要转换:

# 把 0.0~1.0 的滑块值映射到总线音量
AudioServer.set_bus_volume_db(AudioServer.get_bus_index("Music"), linear_to_db(value))
AudioServer.set_bus_mute(AudioServer.get_bus_index("Music"), value <= 0.001)

关键在于改总线而不是改播放器:音乐、音效各自成轨,玩家才能“只关音乐、保留音效”。

3. 按键重绑:运行时改写 InputMap

按键映射存在 InputMap 里,每个 action(如 move_left)可绑多个 event(键盘、手柄、鼠标)。改键的核心三步:

InputMap.action_erase_events("move_left")          # 清掉旧绑定
InputMap.action_add_event("move_left", new_event)  # 写入新事件
# new_event 来自监听捕获:InputEventKey / InputEventJoypadButton

捕获时用 _input() 拿“下一个按下的键”,记得 get_viewport().set_input_as_handled() 防止它同时又触发游戏操作。还要做冲突检测:新键若已被别的 action 占用,要么提示、要么自动顶掉旧的,别让玩家重绑出两个动作抢同一个键。

4. 持久化:ConfigFile 存进 user://

用 ConfigFile 存配置,比手搓 JSON 更省事,格式天然分节:

const PATH := "user://settings.cfg"
func save_settings() -> void:
    var cfg := ConfigFile.new()
    cfg.set_value("audio", "music", music_volume)
    cfg.set_value("display", "fullscreen", is_fullscreen)
    cfg.save(PATH)   # 启动时用 cfg.load(PATH) + cfg.get_value(...) 读回

窗口/全屏改动同步落到 DisplayServer.window_set_mode();写进 user:// 后,只要在 Steamworks 后台开好 Auto-Cloud,玩家的设置就能跟着账号走。

🎯 DeepSeek 提示词

提示词 1:生成一个 Settings 单例(音量 + 显示 + 存取)

适用场景:项目早期搭设置系统骨架,一次拿到可用的 Autoload 脚本。

你是一名资深 Godot 4.x(GDScript)游戏工程师。
任务:为我的 2D 游戏写一个 Autoload 单例 Settings.gd,职责是集中管理玩家设置并在启动时自动加载。
需求:
1) 音频:管理 "Music" / "SFX" / "UI" 三条音频总线音量,值域对外暴露为 0.0~1.0,内部用 linear_to_db 转换;提供 set/get 方法。
2) 显示:管理全屏/窗口模式与分辨率,改动后调用 DisplayServer 相应接口立即生效。
3) 持久化:用 ConfigFile 存到 user://settings.cfg,提供 save_settings() 与 load_settings(),加载缺失时回退默认值。
约束:Godot 4.x 语法;不要使用已废弃 API;所有公开方法写 JSDoc 式注释;默认值集中定义在文件顶部常量区。
输出格式:只输出完整可运行的 Settings.gd 代码,末尾附 5 行以内的注册与调用说明。

提示词 2:生成“按键重绑”UI 逻辑

适用场景:做设置页里的键位重绑面板,重点是捕获、冲突检测与提示。

你是一名 Godot 4.x UI 工程师。
任务:写一段 GDScript,实现“点击按钮 -> 进入监听 -> 捕获下一次按键/手柄事件 -> 写入 InputMap”的重绑流程。
输入:一个 action 名称(如 "move_left")与一个 Button 节点。
输出:一个可复用的 RebindButton 场景脚本。
要求:
1) 点击按钮后按钮文案变为“请按下新按键…”;
2) 用 _input() 捕获下一个 InputEventKey 或 InputEventJoypadButton,忽略鼠标移动等无关事件;
3) 捕获后调用 InputMap.action_erase_events + action_add_event 写入;
4) 做冲突检测:若该键已被其他 action 占用,输出被占用的 action 名并让本次重绑失败;
5) 处理完调用 set_input_as_handled() 防止事件穿透到游戏;Esc 取消监听。
约束:Godot 4.x 语法;不要用已废弃的 scancode API。
输出格式:完整脚本代码 + 一段 3 步的接入说明。

提示词 3:审查并补全我的设置脚本

适用场景:脚本能跑但行为不对(比如音量不生效、切场景后设置丢失),让 DeepSeek 当审查员。

你是 Godot 4.x 代码审查专家,只关注“能否正确工作”,不重写整体风格。
以下是我的设置相关代码与现象:【粘贴代码】【粘贴报错或错误现象,例如:改了音量滑块但音乐没变 / 切回主菜单后恢复默认】。
请按此格式输出:
1) Bug 列表:每条写“位置 / 原因 / 最小修复”;
2) 修复后的关键片段(只给改动部分,用 diff 风格);
3) 一句话验证方法(我该怎么测才能确认修好了)。
约束:不改动无关代码;如果信息不足,先列出你需要我补充的 1-2 个信息。

学习心得

设置菜单看起来“土”,却是把 Demo 变成可上架产品的那道坎——它同时踩中音频、输入、UI、存档、显示五条线,正好是一次把此前所学打通的好机会。对“用 DeepSeek 做一款 Steam 游戏”来说,这类结构清晰、接口固定的模块最适合交给 AI 生成:我只要把总线名、action 名、存储路径这些“项目上下文”喂准,DeepSeek 出的代码基本能直接用。更重要的是,设置菜单逼着我从“能跑”切换到“玩家会用”,这正是独立开发者最容易忽略、也最容易被差评的地方。

明日关注

  • 给设置页补一个“恢复默认”按钮,并列出可选分辨率清单(防止玩家选到不支持的值导致黑屏)。
  • 把设置入口接进主菜单与暂停菜单,验证切换场景后数值仍然生效。
  • 调研 Steam Deck 上设置菜单的字体大小与触控点击区域标准,顺手做一版适配。

本文由自动化学习流水线每日生成,坚持即学即记。