mcpField
G
godot-physics

godot-physics

github.com/gamedev-skills開発5.4k7.0k 回インストール1 日前に更新
リポジトリ

godot-physics について

Godot 4.xの2D・3D物理を扱う開発者向けのスキルガイドです。物理ボディ、衝突、重なり検出、レイ判定に加え、Jolt Physicsの違いも説明します。

主な機能

  1. 01物理ボディタイプの選択
  2. 02衝突レイヤーとマスクの設定
  3. 03Areaによる重なり検出
  4. 04RigidBodyへの力とインパルス
  5. 05レイクエリの実行
  6. 06Jolt Physicsの差異の把握

活用シーン

  1. 01壁や敵との衝突設定
  2. 02トリガーやヒットボックスの作成
  3. 03物理シミュレーション物体の駆動
  4. 04視線や接地の判定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/gamedev-skills/awesome-gamedev-agent-skills --skill godot-physics

インストール後、Claude Code で/godot-physicsを入力して読み込まれたか確認します。

同梱ファイルreferences/bodies-and-queries.md

詳細

Godot Physics(4.x、2D + 3D)

適切な物理ボディを選び、コリジョンレイヤー/マスクを設定し、重なりを検出してレイをキャストします。概念は2Dと3Dの両方に適用できます(2D/3Dのサフィックスを入れ替えてください)。対象はGodot 4.7です。3Dでは、Godot 4.6以降で作成されたプロジェクトはデフォルトでJolt Physicsを実行します。古いプロジェクトでは、切り替えていない限りGodotPhysics3Dが使われます。2Dでは常にGodot独自の2Dエンジンが使われます。

使用する場面

  • ボディタイプの選択、適切なオブジェクト同士が衝突するようにコリジョンレイヤー/マスクを設定する場合、Areaで重なり(トリガー、ヒットボックス)を検出する場合、RigidBodyに力/インパルスを適用する場合、視線や地面のチェック用にレイをキャストする場合に使用します。

使用しない場面: キネマティックキャラクターコントローラー(move_and_slide)→ godot-2d-movement;タイルのコリジョン設定 → godot-tilemap;物理の感触(タイムステップ、質量、ジッター)の調整 → physics-tuning。

基本的なワークフロー

  1. 3Dでは、挙動のデバッグ前に実行中のエンジンを確認します。 Project Settings > Physics > 3D > Physics Engine(project.godot内の[physics] 3d/physics_engine="Jolt Physics")を確認してください。APIは同じですが、ジョイント、レイキャストの面インデックス、キネマティック接触、コリジョンマージンの挙動は異なります(「注意点」を参照)。
  2. ボディタイプを選択します。
    • StaticBody — 動きません(床、壁)。衝突しますが、シミュレーションは行われません。
    • RigidBody — 完全にシミュレーションされます(重力、力、反発)。positionを直接設定せず、力/インパルスを適用するか、linear_velocityを設定してください。
    • CharacterBody — スクリプトで動かすキネマティックボディです(godot-2d-movementを参照)。
    • Area — 重なりを検出し、重力/減衰を適用できます。ソリッドな衝突はありません。 すべてのボディには、子としてCollisionShape(またはCollisionPolygon)が必要です。
  3. レイヤーとマスクを設定します。 ボディは自身のレイヤーに属し、自身のマスクの対象を検知します。一方のボディのレイヤーが他方のマスクに含まれている場合にのみ、2つのボディは相互作用します。わかりやすいように、Project Settings > Layer Namesでレイヤーに名前を付けてください。
  4. Areaのシグナル(body_entered、area_entered)で重なりを検出します。
  5. RigidBodyには力/インパルスを適用します。 または、完全に制御する場合は_integrate_forcesをオーバーライドします。
  6. レイをキャストします。 毎フレームポーリングするRayCast2D/3Dノードを使うか、コードから一度だけスペース状態クエリを実行します。

パターン

1. コリジョンレイヤーとマスク(コードから設定)
# Player is on layer 1, scans layers 2 (walls) and 3 (enemies).
func _ready() -> void:
    set_collision_layer_value(1, true)    # I am on layer 1
    set_collision_mask_value(2, true)     # I collide with things on layer 2
    set_collision_mask_value(3, true)     # ...and layer 3
    # Bit-field forms also exist: collision_layer = 1; collision_mask = 0b110
2. トリガー/ヒットボックスとしてのArea2D
extends Area2D                            # e.g. a damage zone

func _ready() -> void:
    body_entered.connect(_on_body_entered)
    area_entered.connect(_on_area_entered)

func _on_body_entered(body: Node2D) -> void:
    if body.has_method("take_damage"):
        body.take_damage(10)

func _on_area_entered(area: Area2D) -> void:
    print("Overlapped area: ", area.name)
3. RigidBody3Dへの力とインパルスの適用
extends RigidBody3D

func push(direction: Vector3) -> void:
    apply_central_impulse(direction * 8.0)     # instantaneous velocity change

func _physics_process(_delta: float) -> void:
    apply_central_force(Vector3.FORWARD * 4.0) # continuous force (per tick)
    # Never set `position` on a RigidBody to move it; use forces/impulses or
    # set linear_velocity. Use freeze=true if you must hold it in place.
4. 2種類のレイキャスト
# A) RayCast2D node: enable it, then poll after physics has updated.
@onready var ray: RayCast2D = $RayCast2D    # set target_position in the editor

func _physics_process(_delta: float) -> void:
    if ray.is_colliding():
        var hit := ray.get_collider()
        var point := ray.get_collision_point()

# B) One-shot query from code (no node needed).
func ground_under(global_from: Vector2) -> Dictionary:
    var space := get_world_2d().direct_space_state
    var query := PhysicsRayQueryParameters2D.create(global_from, global_from + Vector2(0, 64))
    query.collision_mask = 1                 # only layer 1
    return space.intersect_ray(query)        # {} if nothing hit, else collider/position/normal

注意点

  • レイヤーとマスクの混同は、最も多いバグです。レイヤーは「自分が何であるか」、マスクは「何を探すか」です。AがBを検出するには、BのレイヤーがAのマスクに含まれている必要があります。検出は一方向のみでも可能です。
  • positionによるRigidBodyの移動はソルバーと競合し、すり抜けやジッターを引き起こします。インパルス/力を使うか、linear_velocityを設定するか、freezeしてください。テレポートするには、_integrate_forces内で位置を設定し、速度をゼロにします。
  • Areaがイベントを発生させない場合、監視も監視可能も設定されていないか、レイヤー/マスクが重なっていない可能性があります。Areaが検出するにはmonitoringを有効にする必要があります。ほかのオブジェクトから検出できるようにするには、monitorableを有効にします。
  • RayCast2D/3Dから古いデータが読み取られる、またはデータが取得できない場合、enabledが無効になっているか、物理更新前に読み取っている可能性があります。_physics_process内で読み取り、同じティック内で移動した後はforce_raycast_update()を呼び出してください。
  • CollisionShapeを忘れる(または空のままにする)と、ボディは衝突しません。
  • 高速なオブジェクトは薄い壁をすり抜けることがあります。RigidBodyの連続CD(continuous_cd)を有効にするか、レイキャストに基づくチェックを使ってください。
  • intersect_rayは自身のボディを除外しますか? 自分自身へのヒットを除外するには、query.exclude = [self.get_rid()]を渡してください(ノードの配列ではなく、Array[RID]です)。
Jolt Physics(3D)の違い
  • Jolt では、intersect_ray()/RayCast3D の結果で face_index は常に -1 です。 必要な場合は、Project Settings > Physics > Jolt Physics 3D > Queries > Enable Ray Cast Face Index を有効にしてください(ConcavePolygonShape3D ではメモリ使用量が約25%増加します)。
  • エンジンを切り替えると、ボディが1つだけのジョイントで制限が反転します。 Jolt は ボディ1つだけの場合、そのボディを node_b、node_a をワールドとして扱います。GodotPhysics3D は常に node_a として扱います。ボディを Jolt が想定するスロットに割り当てるか、以前のプロジェクトとの互換性のために Physics > Jolt Physics 3D > Joints > World Node を使用してください。
  • Jolt ではジョイントのソフト制限プロパティは機能しません(例:Pin、Hinge、ConeTwist ジョイントの bias/softness/ relaxation、Slider および Generic6DOF ジョイントの制限の softness/restitution/damping)。デフォルト以外の値に設定すると Godot が警告します。
  • フリーズ中のキネマティックな RigidBody3D は、静的ボディやキネマティックボディとの接触を報告しません。 max_contacts_reported > 0 の場合も同様です。ゲームプレイでこれらの接触が必要な場合は、Physics > Jolt Physics 3D > Simulation > Generate All Kinematic Contacts を有効にしてください。
  • Jolt では、形状の margin は形状に余白を加えるのではなく、縮小します。 そのためサイズは 正確に保たれますが、小さな形状では形状クエリが不自然な法線を返す場合があります。有効な margin は Physics > Jolt Physics 3D > Collisions > Collision Margin Fraction で決まります。
  • Jolt では、Area3D が SoftBody3D に対しても body_entered を発火するようになりました(GodotPhysics3D では発火しません でした)。以前の動作を期待する場合は、レイヤー/マスクでソフトボディを除外してください。

参考資料

  • _integrate_forces、ジョイント、一方向衝突、PhysicsServer の直接アクセス、 形状クエリ(intersect_shape)、3D の move_and_collide については、 references/bodies-and-queries.md をお読みください。
  • Jolt 固有の情報:Godot のドキュメント「Using Jolt Physics」 (https://docs.godotengine.org/en/stable/tutorials/physics/using_jolt_physics.html)。

関連スキル

  • godot-2d-movement — キネマティックな CharacterBody2D コントローラー。
  • godot-tilemap — タイルの衝突形状とそのレイヤー。
  • physics-tuning — エンジンに依存しない操作感の調整:タイムステップ、質量、抵抗、CCD。
  • godot-3d-essentials — これらのボディが配置される3Dシーンのセットアップ。

コメント