physics-system について
Godot 4.3+ でゲーム物理を実装する開発者向けのスキルです。衝突ボディ、形状、クエリ、補間に加え、Jolt Physics とラグドールの設定を扱います。
主な機能
- 014 種類の物理オブジェクトの使い分け
- 02衝突形状、レイヤー、マスクの設定
- 03レイと空間ステートによるクエリ
- 043D 物理での Jolt Physics の利用
- 05補間とラグドールの設定
活用シーン
- 01プレイヤー、敵、オブジェクトの衝突構築
- 02トリガー、重力、オーディオ領域の作成
- 03レイ判定と 3D マウスピッキング
- 04キャラクターへのラグドール物理の追加
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jame581/ godotprompter --skill physics-systemインストール後、Claude Code で/physics-systemを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/area-recipes.mdcollision-layers.mdcollision-shapes.mdinterpolation-camera.mdinterpolation-tuning.mdjolt-differences.mdragdoll-recipes.mdraycasting-recipes.mdrigidbody-recipes.mdsoftbody-recipes.mdstaticbody-recipes.mdtroubleshooting.md詳細
Godot 4.3+ の物理システム
すべての例は、非推奨 API を使用せずに Godot 4.3+ を対象としています。まず GDScript を示し、次に C# を示します。
関連スキル: CharacterBody2D/3D の移動パターンについては player-controller、ヒットボックス/ハートボックスの構成については component-system、物理パフォーマンスの調整については godot-optimization、カメラの追従と補間については camera-system、ネットワーク物理については multiplayer-sync、タイルの衝突設定と 2D キャンバスレイヤーについては 2d-essentials を参照してください。
1. 物理ボディの種類
4 種類の衝突オブジェクトがあります(後半の 3 種類は PhysicsBody2D/3D を継承します)。
| 種類 | 移動方法 | 用途 |
|---|---|---|
Area2D/3D | コード | 重なりの検出、重力ゾーン、オーディオゾーン |
StaticBody2D/3D | 移動しない(または constant_linear_velocity) | 壁、床、コンベアベルト |
RigidBody2D/3D | 物理エンジン | 木箱、投射物、破片、ラグドール |
CharacterBody2D/3D | コード | プレイヤー、敵、NPC(player-controller を参照) |
すべての衝突オブジェクトには、少なくとも 1 つの CollisionShape2D/3D(または CollisionPolygon2D/3D)子ノードが必要です。Jolt Physics は 4.4 以降に組み込み(実験的機能、オプトイン)となり、4.6 以降で作成されたプロジェクトではデフォルトの 3D エンジンです — セクション 8 を参照してください。既存のプロジェクトでは、切り替えるまで GodotPhysics が使われます。2D では常に GodotPhysics が使われます。
重要なルール:
scaleを使って衝突シェイプや物理ボディのスケールを変更してはいけません。シェイプ自体のサイズパラメーター(半径、半寸法、高さ)を使ってください。スケールの変更は衝突精度を損ないます。
2. RigidBody2D/3D
力とインパルス
| メソッド | 効果 | 用途 |
|---|---|---|
apply_force(force, position) | 指定した点に継続的な加速を加える | スラスター、風、磁石 |
apply_central_force(force) | 中心に継続的な加速を加える | 重力、一定の押す力 |
apply_impulse(impulse, position) | 指定した点の速度を瞬時に変化させる | 弾の命中、爆発 |
apply_central_impulse(impulse) | 中心の速度を瞬時に変化させる | ジャンプ、ノックバック |
apply_torque(torque) | 継続的な角加速を加える | 操舵、回転 |
apply_torque_impulse(impulse) | 角速度を瞬時に変化させる | 衝撃による回転 |
apply_force+apply_central_impulse+apply_torqueを使った推進と回転の例(GDScript + C#)については、references/rigidbody-recipes.md を参照してください。
_integrate_forces() — 安全な物理変更
RigidBody のトランスフォーム、速度、角速度を読み取ったり変更したりするには、_physics_process() の代わりに _integrate_forces(state) を使用してください。_physics_process() 内で position や linear_velocity を直接設定すると、物理エンジンと競合します。
警告: ボディがスリープ中は
_integrate_forces()は呼び出されません。コールバックを継続的に実行する必要がある場合はcan_sleep = falseを設定してください。それ以外の場合は、パフォーマンス向上のためにボディをスリープさせてください。
state.apply_force/state.apply_torqueを使った推進とトルクの例(GDScript + C#)については、references/rigidbody-recipes.md を参照してください。
接触モニタリング、PhysicsMaterial、Freeze、look_at
- 接触シグナルを使うには、
contact_monitor = trueとmax_contacts_reported > 0が必要です。設定するとbody_entered/body_exitedが発火します。 PhysicsMaterialリソースは、friction(氷の 0 からゴムの 1)とbounce(0 から 1)を制御します。- フリーズモード:
FREEZE_MODE_STATIC(StaticBody のように動作)またはFREEZE_MODE_KINEMATIC(コードで移動し、他の物体を押す)。 - RigidBody3D の向き: RigidBody に
look_at()を使用してはいけません。代わりに_integrate_forcesを使い、外積による操舵項からstate.angular_velocityを設定してください。
take_damageを使った接触ハンドラー、PhysicsMaterial のプロパティ一覧、フリーズの切り替え、角速度による RigidBody3D のホーミングを含む、GDScript + C# の完全なレシピについては、references/rigidbody-recipes.md を参照してください。
3. StaticBody2D/3D
StaticBodyは物理エンジンによって移動しませんが、constant_linear_velocityを介してほかのボディを押すことができます(例:コンベヤーベルト)。コードで移動させながらCharacterBodyも押すプラットフォームには、**AnimatableBody2D/3D**を使用してください。コードで移動させたStaticBodyでは、CharacterBodyを確実に押せません。
コンベヤーベルトと移動プラットフォームのレシピ(GDScript + C#、Tween駆動のAnimatableBody2Dループ)については、references/staticbody-recipes.mdを参照してください。
4. Area2D/3D
Areaは範囲内の重なりを検出し、物理プロパティを上書きします。衝突応答は発生しないため、ボディはそのまま通過します。Areaがボディを報告するのは、monitoringがオンで、かつそのcollision_maskにボディのcollision_layerが含まれている場合だけです。body_enteredが発火しないよくある原因はこの不一致です。デフォルト(レイヤー1、マスク1)が一致している場合でも、両方の設定を明示してください。ボディ同士の重なりにはbody_entered / body_exitedを接続し、Area同士(ヒットボックス対ダメージ判定ボックス。component-systemを参照)にはarea_entered / area_exitedを使用します。Areaでは、重力(無重力ゾーン、点重力/ブラックホール)、linear_damp / angular_damp(水中、スローモーション)を上書きしたり、音声を特定のAudioBusに転送したりすることもできます。複数のAreaが重なる場合は、priorityで適用順序を決めます。space_overrideモード(COMBINE、REPLACE、COMBINE_REPLACE、REPLACE_COMBINE)を選択してください。
重なり検出の標準的な例(GDScript + C#)、space-overrideモードの参照表、無重力および点重力のレシピについては、references/area-recipes.mdを参照してください。
⚠️ Godot 4.7での変更点: Jolt Physicsでは、
Area3Dがシグナルとメソッドを通じてSoftBody3Dとの重なりを報告するようになりました。不要なArea3D↔SoftBody3Dの相互作用が無視されるよう、衝突レイヤー/マスクを設定してください。4.7移行ガイドを参照してください。
5. Collision Shapes
| 形状(2D / 3D) | 用途 |
|---|---|
Rectangle / Box | 木箱、プラットフォーム、部屋 |
Circle / Sphere | ボール、飛び道具、単純なキャラクター、トリガーゾーン |
Capsule(2Dおよび3D) | キャラクター。丸みがあり、端を滑らかに乗り越えます |
Segment2D / — | 薄い壁、レーザービーム |
SeparationRay2D / 3D | キャラクターの接地スナップ |
WorldBoundary2D / 3D | 無限の床/壁/天井 |
— / Cylinder3D | 柱、樽(GodotPhysicsでは既知のバグがあるため、Joltを推奨) |
動的ボディにはプリミティブを推奨します。ConvexPolygonShapeは高速ですが、穴や内側に湾曲した形状を表現できません。ConcavePolygonShapeはレベルの形状を正確に表現できますが、StaticBody専用で、最も低速です。CollisionShapeノードを移動、回転、拡大・縮小しないでください。形状を変形しないことで、ブロードフェーズの最適化が有効になります。Godot 4.7以降では、横向きの一方向プラットフォーム用にone_way_collision_directionが追加されています。
凸/凹形状のコスト表、形状生成メニュー、パフォーマンスに関するすべてのルール、および4.7以降の一方向の方向指定API(GDScript + C#):references/collision-shapes.md
6. Collision Layers and Masks
Godotでは、次元ごと(2Dと3Dは別々)に32個の物理レイヤーを使用できます。
- collision_layer — このオブジェクトが存在するレイヤー(ほかのオブジェクトはここをスキャンします)
- collision_mask — このオブジェクトがスキャンするレイヤー(検出対象)
考え方: Layerは「自分がいる場所」、Maskは「自分がスキャンする場所」です。オブジェクトAのマスクにオブジェクトBのレイヤーが含まれる場合、またはその逆の場合に衝突が発生します。
レイヤー名はProject Settings → Layer Names → 2D Physics(または3D Physics)で設定します。コードからはset_collision_layer_value(N, true) / set_collision_mask_value(N, true)で設定します(インデックスは1始まりです)。
レイヤーの命名規則、ビットマスクの略記法、Inspectorのエクスポートフラグ、GDScript + C#の例については、references/collision-layers.mdを参照してください。
7. Raycasting and Physics Queries
RayCast2D/3D ノード(毎フレームのシンプルなレイ)
RayCast2D/RayCast3D を子ノードとして追加すると、物理フレームごとに自動でレイをキャストします。is_colliding() と get_collider()/get_collision_point()/get_collision_normal() で結果を取得します。
GDScript と C# の RayCast ノードの例については、references/raycasting-recipes.md を参照してください。
コードベースのレイキャスティング(PhysicsDirectSpaceState)
必要なときにクエリを実行するには、get_world_2d().direct_space_state(または get_world_3d())から空間の状態にアクセスし、PhysicsRayQueryParameters2D/3D.create(from, to) で作成した query を使って intersect_ray(query) を呼び出します。自身を除外するには query.exclude = [get_rid()] を設定し、レイヤーを絞り込むには query.collision_mask を設定します。クエリは _physics_process() 内で実行してください — 物理ステップの実行中は空間がロックされ、物理演算が別スレッドで実行されている場合、空間にアクセスできるのはその中だけです。
自身の除外とマスクによる絞り込みを含む、コードベースのレイキャストの GDScript と C# の完全な例、および 3D のマウスピッキングのレシピについては、references/raycasting-recipes.md を参照してください。
レイの結果、その他のクエリ、3D のマウスピッキング
intersect_ray の結果辞書には position、normal、collider、collider_id、rid、shape が含まれます。PhysicsDirectSpaceState は、intersect_point(ある点で重なっているシェイプ)、intersect_shape(領域クエリ)、cast_motion(シェイプのスイープ)、collide_shape(接触点)、get_rest_info(静止時の衝突情報)にも対応しています。3D のマウスピッキングでは、Camera3D.project_ray_origin(screen_pos) と project_ray_normal(screen_pos) を組み合わせてレイを作成します。
マウスピッキングの完全なレシピ(GDScript と C#)については、references/raycasting-recipes.md を参照してください。
8. Jolt Physics
Jolt は組み込みの代替物理エンジンで、Godot 4.4 から実験的なオプトイン機能として利用できます。(Godot 4.6 以降) Jolt は実験的機能ではなくなり、新規作成した 3D プロジェクトではデフォルトになります。以前のバージョンからアップグレードしたプロジェクトは、変更するまで DEFAULT(GodotPhysics3D)のままです。
Jolt を有効にする
プロジェクト設定 → Physics → 3D → Physics Engine → Jolt Physics → 保存 → エディターを再起動します。(3D のみ。2D では常に GodotPhysics が使用されます。)
メリットと違い
メリット: 積み重ねの安定性が向上し、GodotPhysics で既知の不具合がある CylinderShape3D を問題なく使用でき、SoftBody3D が改善され、アクティブエッジ検出によってゴースト衝突が軽減されます。
GodotPhysics との動作上の違い(安定化、衝突マージン、単一ボディのジョイント、
face_index、未対応のジョイントプロパティ)については、references/jolt-differences.md を参照してください。
⚠️ Godot 4.7 での変更: Jolt Physics では、
WorldBoundaryShape3D.plane.dが Godot Physics と同じ符号規則に従うようになりました。平面の距離は Godot 4.6 とは逆の符号で解釈されます。4.6 の動作を維持するには、符号を反転してください。4.7 移行ガイド を参照してください。
9. 物理補間
物理ティック間の視覚的な動きを滑らかにし、ティックレートとフレームレートが一致しない場合に発生する「階段状」のちらつきをなくします。プロジェクト設定 → Physics → Common → Physics Interpolation で有効にします(4.3 では 2D のみが補間され、3D は 4.4 から対応します)。Godot 4.5 以降では 3D 補間パイプラインが再構成され(RenderingServer → SceneTree)、ネストされたトランスフォームでより正確な結果が得られるようになりました。API に変更はなく、アップグレードすると自動的に改善されます。
基本ルール
- すべてのゲームロジックを
_physics_process()に移動します — 物理ティック以外で設定したトランスフォームはちらつきの原因になります - 物理オブジェクトを動かす Tweens と AnimationPlayer は、物理ティックのタイミングを使用する必要があります
- テレポート後または初期配置後に
reset_physics_interpolation()を呼び出します。「尾を引く」現象を防ぎます
テレポート時のリセット例(GDScript と C#)、ノードごとの
physics_interpolation_modeの制御、ティックレートの目安については、references/interpolation-tuning.md を参照してください。
カメラの補間
物理補間では、カメラに特別な処理が必要です。カメラを独立させる(または top_level = true にする)ことで、_process()(_physics_process() ではありません)で更新し、Node3D.get_global_transform_interpolated() を使ってターゲットの滑らかな位置を取得します(4.4+)。
滑らかに追従する Camera3D の完全な手順(GDScript + C#)については、references/interpolation-camera.md を参照してください。
10. ラグドールシステム
ラグドールはアニメーションを物理演算に置き換え、プロシージャルな死亡表現や爆発、力の抜けたキャラクターを実現します。Skeleton3D → Skeleton メニュー → Create Physical Skeleton から生成します。肩/腰/首には ConeJoint、肘/膝には HingeJoint を使います。PinJoint(デフォルト)では、崩れてしまう傾向があります。physical_bones_start_simulation() で動作させ、Influence でブレンドします。
セットアップ、ジョイントのガイダンス、GDScript + C# による完全な制御、アニメーションブレンド、衝突の例外については、references/ragdoll-recipes.md を参照してください。
11. SoftBody3D
SoftBody3D は変形可能なオブジェクト(布、マント、ゼリーなど)をシミュレートします。メッシュの細分化がシミュレーションを左右し、CollisionShape の子ノードは必要ありません。Jolt Physics を推奨します。 崩壊を防ぐため、Simulation Precision ≥ 5 に設定します。Pressure > 0.0 にするのは閉じたメッシュの場合のみです。
Godot 4.5+ では、RigidBody3D と同様に力を適用する apply_central_impulse() / apply_central_force() が追加されており、すべてのシミュレーションポイントに力が分配されます。
布/マントの手順(PlaneMesh、BoneAttachment3D による固定、Parent Collision Ignore)と、GDScript および C# による 4.5+ の力/インパルス API(爆発によるノックバック、継続的な風)については、references/softbody-recipes.md を参照してください。
⚠️ Godot 4.7 での変更点: Jolt Physics では、
SoftBody3Dの質量は0(自動計算され、ポイントあたり 1 kg となるため、合計質量が非常に大きくなる値)ではなくなり、Godot Physics と同様、ボディ全体で 1 kg がデフォルトになりました。linear_stiffnessの適用方法も変更されているため、アップグレード後にlinear_stiffnessとdamping_coefficientを再調整してください。4.7 移行ガイドを参照してください。
13. 物理演算の問題のトラブルシューティング
症状 → トンネリング、不安定に揺れる積み重ね、スケーリングされたシェイプ、タイル衝突による引っ掛かり、不安定な円柱、物理演算のスパイラル・オブ・デス、原点から遠い場所での浮動小数点精度の問題を網羅した、原因と対処法の簡易表です。
完全な表については、references/troubleshooting.md を参照してください。
14. 実装チェックリスト
- 動的ボディにはプリミティブの衝突シェイプを使用し、凹形シェイプは StaticBodies のみに使用する
- Project Settings で衝突レイヤーに名前を付け、各ボディのレイヤー/マスクを正しく設定する
- 衝突シェイプやボディに
scaleを設定しない — シェイプのサイズパラメーターを直接使用する - RigidBodies の状態は
_physics_process()ではなく、_integrate_forces()で変更する - 接触シグナルが必要な RigidBodies では、
contact_monitor = trueとmax_contacts_reported > 0を設定する - 移動プラットフォームには
AnimatableBody2D/3Dを使用する(StaticBody を手動で動かさない) - コード内のレイキャストには、
_physics_process()内でのみPhysicsDirectSpaceStateを使用する - 物理補間を有効にし、テレポート後/初期配置後に
reset_physics_interpolation()を呼び出す - ラグドールのボーンをキャラクターのカプセルとは別の衝突レイヤーに配置する
- 3D プロジェクトでは Jolt を使用する(Godot 4.6+ では非実験的なデフォルト)