godot-genre-sports について
スポーツゲーム開発向けの Godot スキルで、ボール物理、チームのフォーメーション AI、試合状態管理の実装方法を扱います。物理に沿ったインパルスと権威サーバーによる得点判定に加え、状況別入力や多層コリジョンも取り上げます。
主な機能
- 01マグヌス力と空気抵抗を含むボール物理
- 02フォーメーションスロットによる選手配置
- 03ゴールエリアと試合フェーズの管理
- 04状況に応じた共有ボタンの処理
- 05多層コリジョンエリアによる部位の識別
活用シーン
- 01ボールを選手に固定しないドリブルやシュートの構築
- 02ボールに AI 選手が密集する問題の軽減
- 03高速シュートとゴール判定の検証
- 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.mdskill-chain.mdscripts/body_part_hitbox.gdmagnus_ball_physics.gdpass_predictor.gdsports_ball_physics.gdsports_character.gdsports_patterns.gdsports_umpire_logic.gdstat_modifier_powerup.gdteam_manager.gd詳細
絶対に避けること(エキスパート向けアンチパターン)
物理とボールのインタラクション
- ボールをプレイヤーの Transform の子にすることは絶対に避けてください。必ず独立した
RigidBody3Dとして維持し、apply_central_impulse()を使ってリアルなドリブルの物理挙動を実現してください。 - ボールがゴールを「すり抜ける」ことは絶対に避けてください。高速時の判定を行うため、ボールのプロパティで連続 CCD(
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 に)増やしてください。
- 放送品質の滑らかさを求める場合、物理補間を無効のままにすることは絶対に避けてください。プロジェクト設定で有効にし、高リフレッシュレートのモニターでティック間のボールの Transform を滑らかにしてください。
- ジョイスティック入力のベクトル正規化を省略することは絶対に避けてください。斜め移動が 1.4 倍速くなるのを防ぐため、必ず正規化してください。
- 文脈に応じて変わるボタンを
is_action_pressed()で処理することは絶対に避けてください。Button A が「パス」「タックル」「切り替え」のどれを意味するか判断するには、必ず ContextManager を使用してください。 Area3Dのゴールトリガーを即座に評価することは絶対に避けてください。Physics Server の同期を待つため、必ずawait get_tree().physics_frameを実行してください。
ボール保持の判断ツリー
| 感触 | アプローチ | ルール |
|---|---|---|
| アーケード/磁石のような追従 | 足元へのソフト追従、または短距離のバネ追従 | ボールをプレイヤーの Transform の子にすることは絶対に避けてください。RigidBody3D を権威ある状態に保ってください |
| シミュレーション/インパルスドリブル | タッチごとに apply_central_impulse() で少し前方へ蹴る | 以下の必須ボールスクリプトを優先し、continuous_cd を有効にしてください |
このスキルのデフォルトはインパルスドリブルです。磁石のような吸着は純粋なアーケードジャンルに限る最終手段であり、ボールは自由に動く RigidBody のまま維持する必要があります。
🛠 エキスパート向けコンポーネント(scripts/)
必須 — コーディングの前に、タスクに対応するスクリプトを読んでください。
- ゴール/試合フェーズ → sports_umpire_logic.gd
- 完全な飛行モデル(ドラッグ+
_integrate_forcesによるマグヌス効果) → sports_ball_physics.gd- 簡易なマグヌス効果のみのカーブ(より簡単にアタッチ可能) → magnus_ball_physics.gd — ボールスクリプトは両方ではなく、どちらか一方を選んでください
- フォーメーション/幼稚園サッカーの解消 → team_manager.gd
- 一時的なバフ/パワーアップ → stat_modifier_powerup.gd
- 共通のインパルス/スコア用ヘルパー → sports_patterns.gd
放送用カメラ:このスキルの
scripts/には実装されていません。放送向けの画面構成/アクション時のズームには、関連スキル godot-camera-systems を使用してください。1 つのタスクですべてのスポーツ関連スクリプトを読み込まないでください。
ボールの物理演算(いずれかを選択)
- sports_ball_physics.gd - カスタム積分器による高精度のマグヌス効果+空気抵抗(
continuous_cd対応済み)。 - magnus_ball_physics.gd - 空気抵抗を別の場所で処理する場合に使える、より軽量なマグヌス効果のみの力ヘルパー。
試合/チーム/メタ
- sports_umpire_logic.gd - ゴール用のArea3Dと試合の状態機械(PRE_GAME / ACTIVE / POST_GOAL)。
- team_manager.gd - フォーメーションスロットとチーム戦略の切り替え。
- stat_modifier_powerup.gd - アーケード風パワーアップ用の一時的なプレイヤー/ステータス補正。
- sports_patterns.gd - 物理演算に適したインパルスと、確定的なスコア計算ヘルパー。
スキルチェーン
| フェーズ | スキル | 目的 |
|---|---|---|
| 1. 物理演算 | godot-physics-3d | ボールのバウンド、摩擦、プレイヤー同士の衝突 |
| 2. AI | godot-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()
ステアリングビヘイビア
自然な動き(Seek、Flee、Arrive)を実現します。
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を慎重に調整します。
よくある落とし穴
- AIの団子状態:22人のプレイヤー全員がボールに向かって走ります(幼稚園サッカー)。対策:フォーメーションスロットを使用します。ボールに「プレス」をかけるのは1~2人だけにし、残りはスペースをカバーします。
- 磁石のようなボール:ボールがプレイヤーに完全にくっついてしまいます。対策:ボールをプレイヤーの子要素にするのではなく、物理演算でプレイヤーの少し前方へ蹴り出す「ドリブル」メカニクスを使います。
- 不公平なゴールキーパー:ゴールキーパーが即座に反応します。対策:「反応時間」の遅延と、シュート速度/ステータスに応じた「ミス率」を追加します。
高度なスポーツ向けメタシステム
アニメーション同期、空間認識、衝突フィルタリングのプロフェッショナルな実装です。
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 を調査する場合にのみ「公式ドキュメント」のリンクを開き、関連ドメインにルーティングする際にのみ「関連スキル」を読み込んでください。関連スキル全体を事前に読み込まないでください。
公式ドキュメント
- 物理の概要 — スポーツ選手やボールにおける衝突レイヤー/マスク、連続衝突検出(CD)、RigidBody と CharacterBody の使い分けについて。
- RigidBody の使用 — ボールを親子付けせずにキック/ドリブルするための、インパルス/力の適用タイミング、カスタムインテグレーター、接触モニタリングについて。
- 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 — コンテキストに応じて 1 つのボタンをパス、タックル、切り替えに使い分けるためのアクションマップとデバイスのルーティングについて。
補完
- godot-animation-tree-mastery — ルートモーションの BlendSpace と決定論的なミキサーを設定し、スプリント/シュート/タックル時の滑りを防ぎます。
- godot-camera-systems — ピッチの縮尺に合わせた演出のための、放送向けのフレーミング、アクション時のズーム、追従リグを扱います。
- godot-navigation-pathfinding — NavigationAgent/メッシュ回避を使用し、フォーメーションで走る選手が味方に重ならないようにします。
- godot-state-machine-advanced — 試合フェーズ(キックオフ/プレー/ゴール/終了)と、選手ごとの追跡状態とフォーメーション状態を扱います。
- godot-raycasting-queries — パスコースの確認やタックルの予測に使う、マスク付きの空間クエリを扱います。
- godot-multiplayer-networking — サーバー権限のスコア用 RPC と、高速なスポーツのスナップショット向けの転送モードを扱います。
- godot-adapt-single-to-multiplayer — ローカルでの試合をオンライン対戦に移行する際の、権限の分割とリコンシリエーションを扱います。
- godot-signal-architecture — 審判ロジックをすべての選手ノードに結合させずに、ゴール、ボール保持、UI のイベントバスを構築します。
- godot-3d-world-building — プレイ可能なフィールド周辺のスタジアムの衝突判定、ピッチの表面、LOD 用の小物を扱います。
下流/利用者
- godot-monte-carlo-balancer — 選手/能力の非対称性、キーパーの反応誤差範囲、ラバーバンド AI をシミュレートし、試合の結果が競争力を保てるようにします。
- godot-genre-racing — スポーツが乗り物/アーケード寄りの場合に役立つ、高速物理演算を用いる隣接ジャンルのパターンを扱います(例:Rocket League 風)。
マスター
- godot-master — ライブラリのルーターとミラー化されたモジュールのエントリです。分野横断的なスポーツの課題を担当するドメインスキルを調べる際に開きます。