关于 godot-3d-gameplay
用于在 Godot 中实现 3D 游戏玩法、同时保留项目现有架构的技能。内容涵盖物理、摄像机、灯光和渲染,并通过检查与游戏内验证指导设计。
主要功能
- 01检查项目设置与现有场景
- 02按玩法职责选择物理刚体
- 03基于物理帧构建类型化玩家控制器
- 04配置摄像机支架与输入动作
- 05调节环境灯光以提升可读性
- 06测试玩法、视觉效果与性能
适用场景
- 01为现有 Godot 项目添加玩家控制器
- 02将摄像机碰撞融入关卡几何
- 03针对目标渲染器调节灯光
- 04验证斜坡与平台上的移动
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ pbzona/ godot-skills --skill godot-3d-gameplay安装后在 Claude Code 中输入/godot-3d-gameplay确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/controllers-and-cameras.mdenvironments-and-lighting.mdphysics-testing-and-debugging.md详细介绍
Godot 3D 游戏玩法
将 3D 游戏玩法实现为由物理、摄像机和渲染组成的协调系统。保留项目现有架构,并根据观察到的行为进行调校,而不是用通用控制器替换可正常工作的系统。
编辑前检查
完成检查前,不要编写场景、脚本或项目设置。
- 找到
project.godot并确认项目根目录。读取config/features、渲染方法、物理 tick 频率、显示设置、3D 物理层名称和现有 Input Map 动作。 - 如果可以,使用项目已采用的 Godot 可执行文件运行
--version。API 必须与该确切的 Godot 4.x 版本匹配;不要悄悄升级项目或其资源格式。 - 检查具有代表性的
.tscn、.gd和导入的 3D 资源。记录场景所有权、节点命名、GDScript 类型标注风格、信号风格、分组、自动加载项、文件夹布局,以及节点引用采用导出节点、唯一名称还是路径。 - 检查当前玩家、摄像机、关卡、环境、碰撞层和遮罩、模型缩放、已应用的变换以及输入绑定。编辑前确认网格或资源是否共享。
- 确定目标渲染器和硬件。Forward+ 桌面场景、Mobile 渲染器游戏和 Compatibility 项目需要不同的照明与环境方案。
- 建立可运行的基线并记录现有警告。不要将预先存在的错误归因于本次要求的更改。
如果编辑器版本、项目功能标签与所需 API 不一致,请先停止并解决版本不匹配问题,再创建资源。
选择最精简的合适设计
- 对于需要处理地面、墙壁、斜坡和移动平台行为的脚本驱动角色,使用
CharacterBody3D。 - 对于应能带动角色的脚本或动画驱动平台,使用
AnimatableBody3D。 - 对于运动应由力和冲量决定的物体,使用
RigidBody3D。不要像驱动角色那样,每帧覆盖它的变换。 - 当碰撞、游戏状态、视觉效果和摄像机枢轴的变化原因不同时,将它们放在不同的子分支中。
- 使用 Input Map 动作,而不是物理按键常量,这样键盘和手柄绑定可以共用游戏玩法代码。
- 如果关卡几何体可能移动到主体与摄像机之间,请使用
SpringArm3D摄像机 rig。 - 先从一个
WorldEnvironment和一个主光源开始。只有在基础画面清晰易读后,才添加后期处理和额外的阴影光源。
实现工作流
- 定义可观察的行为:移动参考系、最高速度、加速度、空中操控、斜坡限制、跳跃规则、摄像机范围、摄像机碰撞和视觉目标。
- 创建或调整可复用的玩家场景。将胶囊体或其他简单碰撞体对齐到脚部,让视觉模型变换保持在本地,并将根节点保持在单位变换,以便干净地实例化。
- 在 Input Map 中确认动作名称和死区。语义一致时,复用项目现有动作。
- 在
_physics_process(delta)中实现物理逻辑。将CharacterBody3D.velocity视为每秒单位数,并在每个物理 tick 中调用一次move_and_slide()。 - 除非项目已有输入路由器,否则在
_unhandled_input(event)中处理视角事件。将偏航和俯仰放在不同的枢轴上,并让弹簧臂排除玩家碰撞体。 - 优先配置能提升画面可读性的环境和照明。将天空或背景、环境光贡献、主光方向、曝光、雾效和阴影作为整体进行调校。
- 在具有代表性的几何环境中,将控制器、摄像机和照明放在一起测试,然后再完善动画或特效。
类型化控制器示例
根据检查过的项目调整名称和结构。在 Inspector 中指定 view_camera,并定义 move_left、move_right、move_forward、move_back 和 jump 操作。
extends CharacterBody3D
@export_range(0.1, 30.0, 0.1) var move_speed: float = 7.0
@export_range(0.1, 100.0, 0.1) var ground_acceleration: float = 28.0
@export_range(0.1, 100.0, 0.1) var air_acceleration: float = 9.0
@export_range(0.1, 30.0, 0.1) var jump_velocity: float = 8.5
@export var view_camera: Camera3D
var gravity: float = float(
ProjectSettings.get_setting("physics/3d/default_gravity", 9.8)
)
func _ready() -> void:
assert(is_instance_valid(view_camera), "Assign the movement camera")
func _physics_process(delta: float) -> void:
var move_input: Vector2 = Input.get_vector(
&"move_left", &"move_right", &"move_forward", &"move_back"
)
# Camera +Z points backward, matching the positive Y returned for move_back.
var camera_back: Vector3 = view_camera.global_transform.basis.z
var camera_right: Vector3 = view_camera.global_transform.basis.x
camera_back.y = 0.0
camera_right.y = 0.0
camera_back = camera_back.normalized()
camera_right = camera_right.normalized()
var wish_direction: Vector3 = (
camera_right * move_input.x + camera_back * move_input.y
).limit_length(1.0)
var target_velocity: Vector3 = wish_direction * move_speed
var response: float = (
ground_acceleration if is_on_floor() else air_acceleration
)
velocity.x = move_toward(velocity.x, target_velocity.x, response * delta)
velocity.z = move_toward(velocity.z, target_velocity.z, response * delta)
if is_on_floor():
if velocity.y < 0.0:
velocity.y = 0.0
if Input.is_action_just_pressed(&"jump"):
velocity.y = jump_velocity
else:
velocity.y -= gravity * delta
move_and_slide()
在物理体上调整 floor_max_angle、floor_snap_length、floor_stop_on_slope、平台层和 platform_on_leave,而不是自行重新实现这些行为。只有在游戏规格要求时,才添加土狼时间、跳跃缓冲、冲刺或根运动。
验证
先运行项目自身的检查,然后执行所有适用步骤:
- 使用匹配的编辑器导入并解析项目。如果项目支持无头验证,请运行
<godot> --headless --path <project> --editor --quit并检查完整输出。 - 运行玩家场景和至少一个集成关卡。确认当前只有一个活动的游戏摄像机。
- 测试启动、停止、反向、对角线输入、无输入减速、按下与按住跳跃、接触天花板、边缘、楼梯、缓坡和超出限制的斜坡、墙壁、角落以及移动平台。
- 在完整范围内旋转摄像机。检查移动方向、俯仰限制、摄像机碰撞、障碍后的恢复、近裁剪面交叉以及鼠标捕获释放。
- 在低帧率和高帧率下测试,同时保持物理行为稳定。检查摄像机平滑和动画代码是否受帧率影响。
- 使用可见碰撞形状和远程场景树,验证碰撞体对齐、层、遮罩、活动环境和运行时变换。
- 对比有代表性的暗处、亮处、室内和室外画面。检查曝光、轮廓、阴影痤疮、阴影分离、雾效可读性和材质响应。
- 在目标级别的硬件上进行性能分析,然后再决定是否保留开销较大的阴影、体积效果、屏幕空间效果或大量动态光源。
- 重新运行基线检查,并报告更改的文件、设置、测试,以及无法执行的设备或视觉检查。
常见问题
- 在调用
move_and_slide()前将CharacterBody3D.velocity乘以delta;物理体需要的是速度,而非逐帧位移。 - 通过
position或global_transform移动物理体,却期望滑动碰撞或地面状态仍然可靠。 - 直接使用摄像机带俯仰角的前向向量,导致出现不必要的垂直移动。
- 将摄像机直接挂到动画视觉骨骼下,或旋转整个玩家来控制摄像机瞄准。
- 为精细渲染网格使用同样精细的碰撞体,或使用非均匀缩放的碰撞形状。
- 将
is_on_floor()当作预测查询;它描述的是上一次move_and_slide()的结果。 - 项目设置已经定义键位、碰撞层编号、节点路径或重力时,仍将其硬编码。
- 未检查渲染器支持情况和 GPU 开销,就启用所有环境效果。
- 只需更改某个场景实例时,却修改了共享的
Environment、材质、网格或形状资源。 - 将无头解析视为视觉验证;摄像机、材质、阴影和雾效仍需通过渲染画面检查。
参考资料
评论
支持 Markdown