mcpField
G
godot-3d-gameplay

godot-3d-gameplay

github.com/pbzona开发242 次安装14 周前更新
代码仓库

关于 godot-3d-gameplay

用于在 Godot 中实现 3D 游戏玩法、同时保留项目现有架构的技能。内容涵盖物理、摄像机、灯光和渲染,并通过检查与游戏内验证指导设计。

主要功能

  1. 01检查项目设置与现有场景
  2. 02按玩法职责选择物理刚体
  3. 03基于物理帧构建类型化玩家控制器
  4. 04配置摄像机支架与输入动作
  5. 05调节环境灯光以提升可读性
  6. 06测试玩法、视觉效果与性能

适用场景

  1. 01为现有 Godot 项目添加玩家控制器
  2. 02将摄像机碰撞融入关卡几何
  3. 03针对目标渲染器调节灯光
  4. 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.md
environments-and-lighting.md
physics-testing-and-debugging.md

详细介绍

Godot 3D 游戏玩法

将 3D 游戏玩法实现为由物理、摄像机和渲染组成的协调系统。保留项目现有架构,并根据观察到的行为进行调校,而不是用通用控制器替换可正常工作的系统。

编辑前检查

完成检查前,不要编写场景、脚本或项目设置。

  1. 找到 project.godot 并确认项目根目录。读取 config/features、渲染方法、物理 tick 频率、显示设置、3D 物理层名称和现有 Input Map 动作。
  2. 如果可以,使用项目已采用的 Godot 可执行文件运行 --version。API 必须与该确切的 Godot 4.x 版本匹配;不要悄悄升级项目或其资源格式。
  3. 检查具有代表性的 .tscn、.gd 和导入的 3D 资源。记录场景所有权、节点命名、GDScript 类型标注风格、信号风格、分组、自动加载项、文件夹布局,以及节点引用采用导出节点、唯一名称还是路径。
  4. 检查当前玩家、摄像机、关卡、环境、碰撞层和遮罩、模型缩放、已应用的变换以及输入绑定。编辑前确认网格或资源是否共享。
  5. 确定目标渲染器和硬件。Forward+ 桌面场景、Mobile 渲染器游戏和 Compatibility 项目需要不同的照明与环境方案。
  6. 建立可运行的基线并记录现有警告。不要将预先存在的错误归因于本次要求的更改。

如果编辑器版本、项目功能标签与所需 API 不一致,请先停止并解决版本不匹配问题,再创建资源。

选择最精简的合适设计

  • 对于需要处理地面、墙壁、斜坡和移动平台行为的脚本驱动角色,使用 CharacterBody3D。
  • 对于应能带动角色的脚本或动画驱动平台,使用 AnimatableBody3D。
  • 对于运动应由力和冲量决定的物体,使用 RigidBody3D。不要像驱动角色那样,每帧覆盖它的变换。
  • 当碰撞、游戏状态、视觉效果和摄像机枢轴的变化原因不同时,将它们放在不同的子分支中。
  • 使用 Input Map 动作,而不是物理按键常量,这样键盘和手柄绑定可以共用游戏玩法代码。
  • 如果关卡几何体可能移动到主体与摄像机之间,请使用 SpringArm3D 摄像机 rig。
  • 先从一个 WorldEnvironment 和一个主光源开始。只有在基础画面清晰易读后,才添加后期处理和额外的阴影光源。

实现工作流

  1. 定义可观察的行为:移动参考系、最高速度、加速度、空中操控、斜坡限制、跳跃规则、摄像机范围、摄像机碰撞和视觉目标。
  2. 创建或调整可复用的玩家场景。将胶囊体或其他简单碰撞体对齐到脚部,让视觉模型变换保持在本地,并将根节点保持在单位变换,以便干净地实例化。
  3. 在 Input Map 中确认动作名称和死区。语义一致时,复用项目现有动作。
  4. 在 _physics_process(delta) 中实现物理逻辑。将 CharacterBody3D.velocity 视为每秒单位数,并在每个物理 tick 中调用一次 move_and_slide()。
  5. 除非项目已有输入路由器,否则在 _unhandled_input(event) 中处理视角事件。将偏航和俯仰放在不同的枢轴上,并让弹簧臂排除玩家碰撞体。
  6. 优先配置能提升画面可读性的环境和照明。将天空或背景、环境光贡献、主光方向、曝光、雾效和阴影作为整体进行调校。
  7. 在具有代表性的几何环境中,将控制器、摄像机和照明放在一起测试,然后再完善动画或特效。

类型化控制器示例

根据检查过的项目调整名称和结构。在 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