mcpField
G
godot-genre-sports

godot-genre-sports

github.com/thedivergentai开发907250 次安装2 周前更新
代码仓库

关于 godot-genre-sports

面向 Godot 体育游戏开发的技能,提供球体物理、球队阵型 AI 和比赛状态管理的实现指导。内容侧重物理安全的冲量与权威判分,并涵盖情境输入和分层碰撞区域。

主要功能

  1. 01实现带旋转力与空气阻力的球体物理
  2. 02使用阵型槽分配球队位置
  3. 03管理进球区域和比赛阶段
  4. 04通过上下文处理共享按键
  5. 05以分层碰撞区域区分身体部位

适用场景

  1. 01制作不依附于球员的运球与射门
  2. 02减少球队 AI 全员追球的聚集
  3. 03校验高速射门和进球触发
  4. 04为传球、抢断和换人复用按键

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/thedivergentai/game-dev-agentic-skills --skill godot-genre-sports

安装后在 Claude Code 中输入/godot-genre-sports确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
migration-notes.md
skill-chain.md
scripts/
body_part_hitbox.gd
magnus_ball_physics.gd
pass_predictor.gd
sports_ball_physics.gd
sports_character.gd
sports_patterns.gd
sports_umpire_logic.gd
stat_modifier_powerup.gd
team_manager.gd

详细介绍

切勿这样做(专家级反模式)

物理与球体交互
  • 切勿将球直接设为玩家 Transform 的子级;必须让它保持为独立的 RigidBody3D,并使用 apply_central_impulse() 实现逼真的带球物理效果。
  • 切勿让球“穿过”球门;必须在球的属性中启用连续碰撞检测(continuous_cd = true),以支持高速状态下的检测。
  • 切勿对 CollisionShape3D 进行非均匀缩放;必须调整资源半径,以保持内部转动惯量。
  • 切勿在 _process() 中施加冲量;必须使用 _physics_process() 或 _integrate_forces(),以避免画面抖动。
  • 切勿只用一个碰撞形状表示角色;必须使用分层形状,分别对应头部、躯干和腿部,以支持头球和胸部停球。
比赛与球队 AI
  • 切勿让所有 AI 都去追球(“幼儿园足球”);必须实现阵型站位(防守/进攻),仅让距离最近的 1-2 名球员参与争抢。
  • 切勿让守门员拥有完美反应;必须加入反应延迟(0.2s-0.5s),并根据射门角度和速度设定“失误率”。
  • 切勿忽略移动时的根运动;必须结合根运动使用 AnimationTree,确保动量和转向在视觉上有真实感。
  • 切勿信任客户端对进球的判定;必须要求权威服务器验证物理状态和得分逻辑。
实现与同步
  • 切勿依赖默认物理更新频率(60 TPS)处理高速球体运动;必须提高 physics_ticks_per_second(例如设为 120 或 240),以避免穿透。
  • 如果想要达到广播级的流畅度,切勿禁用物理插值;在项目设置中启用它,让高刷新率显示器上的球体变换在物理更新之间平滑过渡。
  • 切勿跳过摇杆输入的向量归一化;必须进行归一化,以避免斜向移动速度快 1.4 倍。
  • 切勿使用 is_action_pressed() 处理上下文相关按钮;必须使用ContextManager 判断按钮 A 表示“传球”、“抢断”还是“切换”。
  • 切勿立即检查 Area3D 球门触发器;必须执行 await get_tree().physics_frame,以便物理服务器完成同步。

控球决策树

手感方式规则
街机/磁吸式轻柔跟随,或使用短距离弹簧效果将球拉向脚下仍然绝不能将球重新设为玩家 Transform 的子级;让 RigidBody3D 保持权威
模拟/冲量带球每次触球时使用 apply_central_impulse() 将球踢向前方一点优先使用下方的必需球体脚本;启用 continuous_cd

此技能的默认方式:冲量带球。磁吸效果仅是纯街机类游戏的最后手段,而且球必须始终是独立的 RigidBody。


🛠 专家组件(scripts/)

必需 — 编写代码前,请阅读与任务对应的脚本:

广播镜头:此技能的 scripts/ 中尚未实现。广播构图/动作时缩放请使用同级技能 godot-camera-systems。

切勿加载所有体育脚本来完成单个任务。

球体物理(任选其一)
  • sports_ball_physics.gd - 通过自定义积分器实现高保真马格努斯效应和空气阻力(已准备好使用 continuous_cd)。
  • magnus_ball_physics.gd - 更精简的马格努斯效应力辅助工具,适用于由其他部分处理阻力的情况。
比赛 / 球队 / 元数据

技能链

阶段技能用途
1. 物理godot-physics-3d球体弹跳、摩擦、球员碰撞
2. AIgodot-state-machine-advanced、godot-navigation-pathfinding阵型、盯防、避让
3. 动画godot-animation-tree-mastery混合跑动、射门、铲球动画
4. 输入godot-input-handling上下文相关按钮(传球 / 铲球共用按钮)
5. 摄像机godot-camera-systems转播视角 / 动作时缩放(同级技能,非本地脚本)

架构概览

1. 球体(物理核心)

最重要的对象,手感必须到位。

# ball.gd
extends RigidBody3D

@export var drag_coefficient: float = 0.5
@export var magnus_effect_strength: float = 2.0

func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
    # Apply Air Drag
    var velocity = state.linear_velocity
    var speed = velocity.length()
    var drag_force = -velocity.normalized() * (drag_coefficient * speed * speed)
    state.apply_central_force(drag_force)
    
    # Magnus Effect (Curve)
    var spin = state.angular_velocity
    var magnus_force = spin.cross(velocity) * magnus_effect_strength
    state.apply_central_force(magnus_force)
2. 球队 AI(阵型)

AI 球员不会只朝球跑,而是跑向相对于球或球场的位置。

# team_manager.gd
extends Node

enum Strategy { ATTACK, DEFEND }
var current_strategy: Strategy = Strategy.DEFEND
var formation_slots: Array[Node3D] # Markers parented to a "Formation Anchor"

func update_tactics(ball_pos: Vector3) -> void:
    # Move the entire formation anchor
    formation_anchor.position = lerp(formation_anchor.position, ball_pos, 0.5)
    
    # Assign best player to each slot
    for player in players:
        var best_slot = find_closest_slot(player)
        player.set_target(best_slot.global_position)
3. 比赛管理器

裁判逻辑。

# match_manager.gd
var score_team_a: int = 0
var score_team_b: int = 0
var match_timer: float = 300.0
enum State { KICKOFF, PLAYING, GOAL, END }

func goal_scored(team: int) -> void:
    if team == 0: score_team_a += 1
    else: score_team_b += 1
    current_state = State.GOAL
    play_celebration()
    await get_tree().create_timer(5.0).timeout
    reset_positions()
    current_state = State.KICKOFF

关键机制实现

上下文相关输入

“A”按钮会根据上下文执行不同操作。

func _unhandled_input(event: InputEvent) -> void:
    if event.is_action_pressed("action_main"):
        if has_ball:
            pass_ball()
        elif is_near_ball:
            slide_tackle()
        else:
            switch_player()
转向行为

实现自然移动(追寻、逃离、减速到达)。

func seek(target_pos: Vector3) -> Vector3:
    var desired_velocity = (target_pos - global_position).normalized() * max_speed
    var steering = desired_velocity - velocity
    return steering.limit_length(max_force)

Godot 专属提示

  • NavigationServer3D:避开障碍物(其他球员 / 裁判)必不可少。
  • AnimationTree(BlendSpace2D):对体育游戏至关重要。需要在所有方向上实现 Idle -> Walk -> Jog -> Sprint 之间的平滑混合。
  • PhysicsMaterial:仔细调整球体和球场碰撞体的 bounce 和 friction。

常见问题

  1. AI 扎堆:22 名球员全都朝球跑(幼儿园足球)。解决方案:使用阵型站位。只有 1-2 名球员“逼抢”持球队员;其他球员负责覆盖空间。
  2. 磁性球:球与球员贴合得过于完美。解决方案:使用“盘带”机制,让球员在物理意义上将球踢到前方一点,而不是将球设为其子节点。
  3. 不公平的守门员:守门员瞬间做出反应。解决方案:根据射门速度 / 属性,加入“反应时间”延迟和“失误率”。

高级体育游戏元系统

动画同步、空间智能和碰撞过滤的专业实现。

1. 根运动过渡(AnimationTree)

利用 AnimationMixer 类(及其衍生类,如 AnimationTree)从复杂动画中提取根运动。这可确保角色的物理位移由动画数据直接驱动,避免出现“滑步”,并确保高速转向或射门时的动量在视觉上真实可信。

class_name SportsCharacter extends CharacterBody3D

@onready var anim_tree: AnimationTree = $AnimationTree

func _physics_process(_delta: float) -> void:
    # Extract root motion from the current animation state
    var root_motion := anim_tree.get_root_motion_position()
    # Apply to velocity for physics-synced movement
    velocity = (global_transform.basis * root_motion) / _delta
    move_and_slide()
2. 上下文传球预测(射线投射)

要预测传球路线是否畅通,请配置 PhysicsRayQueryParameters3D 对象,并使用 PhysicsDirectSpaceState3D.intersect_ray()。这样 AI 或玩家辅助系统就能在执行动作前,确认通往队友的路径畅通无阻。

class_name PassPredictor extends Node3D

func is_lane_clear(target_pos: Vector3) -> bool:
    var space_state := get_world_3d().direct_space_state
    var query := PhysicsRayQueryParameters3D.create(global_position, target_pos)
    query.collision_mask = 1 # Environment/Opponents
    
    var result := space_state.intersect_ray(query)
    return result.is_empty() # Path is clear if no collision
3. 分层命中箱模式

配置 Area3D 节点的 collision_layer 和 collision_mask 属性,以过滤交互。通过为球体和特定身体部位(头部、躯干、腿部)分配不同图层,你可以准确检测头球、胸部停球或滑铲时的上下文重叠。

class_name BodyPartHitbox extends Area3D

enum Part { HEAD, TORSO, LEGS }
@export var part_type: Part

func _on_ball_entered(ball: RigidBody3D) -> void:
    match part_type:
        Part.HEAD:
            apply_header_force(ball)
        Part.TORSO:
            apply_chest_trap(ball)
        Part.LEGS:
            apply_kick_force(ball)

专家提示:对于“根运动”系统,请确保将 AnimationTree 的 deterministic 属性设为 true,以确保不同硬件上的位移一致。

深入配方(按需)

主题参考资料 / 脚本
技能链与阶段路由skill-chain.md

参考资料

渐进式披露:仅在研究特定 API 时打开官方文档链接;在路由到相邻领域时加载相关技能——不要预加载整个技能网络。

官方文档
  • 物理学简介 — 碰撞层/遮罩、连续碰撞检测,以及刚体和角色体分别适用于体育游戏中的球员与球的场景。
  • 使用刚体 — 冲量/力的时机、自定义积分器和接触监测,实现在不将球设为子节点的情况下踢球/带球。
  • RigidBody3D — 高速弹道运动所需的 continuous_cd、阻尼以及 apply_central_impulse / 力 API。
  • PhysicsDirectBodyState3D — 使用 _integrate_forces 状态施加马格努斯力/阻力等自定义力,同时避免与求解器冲突。
  • PhysicsMaterial — 球和球场表面的弹跳/摩擦力覆盖设置。
  • 碰撞形状(3D) — 正确设置球体/胶囊体尺寸,确保惯性和分层命中箱在物理上有效。
  • 物理插值 — 在较高频率的物理帧之间平滑呈现球和球员的变换。
  • 空闲处理与物理处理 — 将冲量和比赛规则放在 _physics_process / 积分路径中,避免抖动。
  • 射线投射 — 通过 PhysicsDirectSpaceState3D 查询传球路线和抢断辅助。
  • 使用 AnimationTree — 用于扎根移动的 BlendSpace 混合和根运动提取,包括急转和射门。
  • 控制器、游戏手柄与操纵杆 — 规范化摇杆轴、设备 ID 和振动,用于根据情境处理传球/抢断/切换。
  • 高级多人游戏 — 在竞技比赛中权威验证进球,并以不可靠方式同步移动。
相关技能
前置条件
  • godot-project-foundations — 在引入球和队伍系统之前,配置自动加载、物理帧/插值项目设置和场景布局。
  • godot-physics-3d — 球和分层命中箱所依赖的 RigidBody3D、层/遮罩和连续碰撞模式。
  • godot-input-handling — 配置动作映射和设备路由,使同一个按钮能根据情境执行传球、抢断或切换。
补充
下游/使用者
  • godot-monte-carlo-balancer — 模拟球员/属性差异、守门员反应误差区间和橡皮筋 AI,让比赛结果保持竞争性。
  • godot-genre-racing — 体育项目偏向载具/街机风格时可参考的相邻高速物理类型模式(例如 Rocket League 风格)。
主入口
  • godot-master — 技能库路由器和镜像模块入口;探索哪个领域技能负责跨领域的体育相关问题时可打开。

评论

支持 Markdown