今日速览
- Godot 输入分两种处理模式:事件(
_input()响应按下瞬间,如跳跃)与轮询(Input.is_action_pressed()持续查询,如移动),先分清场景再写代码。 - InputMap 输入动作是官方推荐做法:给动作起名(如
move_left),一个动作可绑多个按键/手柄按键,天然支持多设备与自定义键位。 Input.get_vector()一行代码拿到 8 方向归一化输入向量,是 2D 移动的标准起点。- 角色移动永远用
move_and_slide()/move_and_collide(),不要直接改position——否则没有碰撞检测,会穿墙。 - 平台跳跃角色用
MOTION_MODE_GROUNDED(默认),重力要自己在代码里算,物理引擎不会替 CharacterBody2D 施加重力。
核心学习内容
1. 事件 vs 轮询:两种输入模式怎么选
Godot 官方文档把输入分成两类场景:
- 一次性事件(按下”跳跃”键的那一瞬间):用
_input(event)回调 +event.is_action_pressed("jump")。适合跳跃、攻击、打开背包、确认键这类”按一下触发一次”的操作。 - 持续状态(按住方向键期间一直移动):用
Input.is_action_pressed("move_right")轮询。放在_physics_process()里每物理帧查询,适合移动、冲刺、蓄力。
判断口诀:“按一下”用事件,“按住期间持续生效”用轮询。 两者可混用:移动轮询、跳跃事件,互不冲突。
2. InputMap:用”动作名”而不是”键名”写代码
新手常见错误是直接写 if event.keycode == KEY_D——这叫硬编码,玩家想改键位就要改代码。正确做法是 InputMap 动作:
- 打开 项目设置 → InputMap 标签页,新建动作
move_left、move_right、jump等; - 每个动作可以绑多个输入:
move_left同时绑A、←、手柄左摇杆负方向; - 代码里只认动作名:
Input.is_action_pressed("move_left")、Input.get_vector("move_left", "move_right", "move_up", "move_down")。
官方建议动作名用 snake_case,新项目自带 ui_left 等内置动作(勾选 Show Built-in Actions 可见)。用动作的好处:键位配置、手柄适配、未来做”自定义按键设置”全部免费。注意键盘存在 ghosting 问题(低端键盘同时按 3 键以上会丢输入),默认键位尽量选键盘上互不冲突的布局(如 WASD 而非同排相邻键)。
3. CharacterBody2D:会碰撞的角色底盘
CharacterBody2D 是”由代码控制、受碰撞影响、不受物理引擎力影响”的刚体——重力、摩擦都要自己写,但换来的是精确可控(这也是平台跳跃游戏普遍选它的原因)。核心规则:
- 移动只允许在
_physics_process()里调用move_and_slide()或move_and_collide(); - 禁止直接改
position,否则绕过碰撞检测; move_and_slide():自动处理”沿墙滑动”,适合平台跳跃/俯视角。它读取velocity属性、up_direction(默认朝上)、floor_max_angle(默认 45°,超过就按墙算),并在碰撞后自动修正velocity;move_and_collide(velocity * delta):只移动并返回碰撞信息,适合子弹反弹、需要自定义碰撞反应的场合。其实move_and_slide()等价于move_and_collide()+velocity.slide(碰撞法线)的循环封装,先用move_and_slide()就对了;- 碰撞后检测:
is_on_floor()/is_on_wall()/is_on_ceiling()(GROUNDED 模式),以及get_slide_collision_count()+get_slide_collision(i)拿到具体撞到了谁(例如踩到敌人判定)。
官方”最简移动”模板(俯视角):
extends CharacterBody2D
var speed = 300
func get_input():
var input_dir = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
velocity = input_dir * speed
func _physics_process(delta):
get_input()
move_and_collide(velocity * delta)
4. 把”能动”升级成”手感好”:加速、摩擦与跳跃
直接 velocity = input_dir * speed 的问题是急停急起,手感僵硬。进阶做法是给水平速度加”逼近目标速度”的平滑(lerp),跳跃则用 is_on_floor() 防止空中二段跳,加重力后再 move_and_slide():
extends CharacterBody2D
@export var speed := 300.0
@export var acceleration := 10.0 # 越大响应越快
@export var friction := 12.0
@export var gravity := 980.0
@export var jump_velocity := -400.0
func _physics_process(delta):
# 重力
if not is_on_floor():
velocity.y += gravity * delta
# 水平输入 + 平滑
var input_dir := Input.get_axis("move_left", "move_right")
if input_dir != 0:
velocity.x = move_toward(velocity.x, input_dir * speed, acceleration * speed * delta)
else:
velocity.x = move_toward(velocity.x, 0, friction * speed * delta)
# 跳跃(事件式输入放这里也 OK,用 just_pressed 变体)
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = jump_velocity
move_and_slide()
move_toward 让速度平滑逼近目标,配合第 8-2 天学的手感调优(加速度、摩擦系数),角色就从”滑板”变成”稳重的角色”。
🎯 DeepSeek 提示词
① 生成平台跳跃角色控制器(适用:项目起步,让 DeepSeek 写完整角色脚本)
你是一名资深 Godot 4 游戏开发者。请为我的 2D 平台跳跃游戏写一个 CharacterBody2D 角色控制器脚本。
需求:
1. 使用 InputMap 动作名:move_left / move_right / jump / dash(我已在项目设置里定义好);
2. 包含:重力、地面加速与空中加速度分离、跳跃(按住跳得更高,即 variable jump height)、
落地检测 is_on_floor()、土狼时间(coyote time 0.1 秒);
3. 所有手感参数(speed / gravity / jump_velocity / acceleration 等)用 @export 暴露到 Inspector;
4. 只用 move_and_slide(),禁止直接修改 position;
5. 输出:完整 GDScript 代码 + 每段核心逻辑 2-3 行注释 + 参数默认值推荐表(含"爽快型/沉稳型"两套取值)。
使用说明:复制到 DeepSeek 对话框即可,输出直接保存为 player.gd 挂到 CharacterBody2D 节点;若提示词里提到的动作名没建,先在 InputMap 里补齐。
② 配置多设备输入(适用:想让游戏同时支持键盘 + 手柄)
你是 Godot 4 输入系统专家。我的 2D 游戏目前只支持键盘 WASD,想支持 Xbox 手柄。
请输出:
1. 一份 InputMap 动作配置清单:动作名(snake_case)、每个动作要绑定的所有输入
(键盘键位 + 手柄按钮/摇杆轴),例如 move 用左摇杆、jump 用手柄 A 键;
2. 对应 GDScript:在 _ready() 里用 InputMap.action_add_event() 把这些绑定写成代码
(这样玩家改键后重启不会丢配置),并处理"手柄摇杆死区"设置(InputMap.action_set_deadzone);
3. 检查清单:列出 3 个手柄常见坑(如轴值范围 -1~1、按下事件重复触发、拔插手柄)
以及对应规避写法。
使用说明:这个提示词把”键位配置”变成代码,适合在游戏设置界面做”自定义按键”功能时直接复用。
③ Debug 角色移动脚本(适用:角色不动/穿墙/抖动,让 DeepSeek 当审查员)
你是 Godot 4 资深调试专家。下面是我的角色移动脚本,请逐行审查并指出所有 bug:
[粘贴你的 player.gd 完整代码]
重点检查:
1. 是否在 _physics_process 里移动、是否误用了 position 直接赋值;
2. delta 是否被正确使用(如 velocity *= delta 或漏乘);
3. 跳跃逻辑是否被每帧重复触发(应只在按下瞬间触发);
4. InputMap 动作名是否与代码里的字符串一致(列出代码中出现的所有动作名,
提示我核对项目设置);
5. move_and_slide 调用顺序是否正确(先改 velocity 再调用)。
输出格式:按严重程度列出问题(致命/建议),每个问题给出修改后的代码片段。
使用说明:把报错脚本原样贴进提示词,DeepSeek 会按清单逐项排查——这是每天学到的”调试提示词模板”最直接的应用。
学习心得
对「用 DeepSeek 从零做 Steam 游戏」来说,输入与角色控制是第一个必须自己跑通的硬骨头:美术可以靠 AI 生成、数值可以靠 AI 计算,但”按 A 键角色必须往前走”这种物理帧逻辑,AI 生成的代码需要你理解 API 才能排查。今天学到的关键心智模型只有三个:事件 vs 轮询(决定代码结构)、InputMap 动作(决定可维护性)、move_and_slide 契约(决定会不会穿墙)。把这三点讲给 DeepSeek 听(写进提示词做约束),它生成的代码就会一次比一次靠谱。下一步就是把这个控制器接上第 14 天的 FSM 敌人 AI,让主角和敌人动起来。
明日关注
- 学习 Godot 动画系统(AnimationPlayer / AnimationTree),把角色移动与跑步动画绑定
- 用提示词①生成主角控制器,并试跑”爽快型”参数组,记录手感差异
- 在 InputMap 里为手柄建好全套动作,用提示词②生成代码并测试摇杆死区
本文由自动化学习流水线每日生成,坚持即学即记。
评论