godot-game-loop-time-trial について
godot-game-loop-time-trialは、チェックポイント順序の検証、精密な計時、ゴースト再生を扱うGodot向けスキルです。マネージャー、チェックポイント、記録、再生、リーダーボードの各要素の実装を案内します。
主な機能
- 01チェックポイント順序の検証
- 02マイクロ秒または物理フレーム計時
- 03Quaternion回転を含む変換記録
- 04補間によるゴースト再生
- 05リーダーボード時間の書式設定
活用シーン
- 01チェックポイント式レースタイマーの構築
- 02ゴースト走行の記録と再生
- 03ベストタイムとゴーストデータの保存
- 04リーダーボード向けラップ記録の整形
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ thedivergentai/ game-dev-agentic-skills --skill godot-game-loop-time-trialインストール後、Claude Code で/godot-game-loop-time-trialを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/migration-notes.mdtime-trial-expert-patterns.mdscripts/ghost_recorder.gdghost_replayer.gdtime_trial_leaderboard_bridge.gdtime_trial_manager.gdtime_trial_patterns.gdtime_trial_playback_buffer.gd詳細
アーキテクチャ設計:「検証チェーン」パターン
上級実装では、タイムトライアルを状態検証済みシーケンスとして扱います。タイムの記録は簡単ですが、ショートカットによる不正を防ぐには、順序を厳密に管理するCheckpointManagerが必要です。
主な責務
- TimeTrialManager:中心となる時計です。チェックポイントの順序を検証し、「ベストラップ」の処理を行います。
- GhostRecorder:高頻度のトランスフォームデータを記録します。フレームレートに依存しない再生のため、デルタタイムのタイムスタンプを使用します。
- Checkpoint:マネージャーに通知する空間トリガーです。
上級者向けコードパターン
1. 堅牢なチェックポイント検証
チェックポイントを番号順に通過することを必須にして、「ショートカットによる不正」を防ぎます。
Areaのbody_entered(物理)をTimeTrialManager.pass_checkpoint(index)に接続します。マネージャーがマイクロ秒単位の計時を管理します。スクリプトを参照してください。
2. 容量効率の高いゴースト再生
固定レート(例:10 Hz)でサンプリングします。位置はLerpし、回転はQuaternionをslerpします(ghost_recorder.gd/ghost_replayer.gd)。ゴーストの進行方向をEuler角でLerpしないでください。
上級者向け判断マトリクス:データストレージ
| 形式 | 最適な用途 | 実装 |
|---|---|---|
| Dictionary Array | プロトタイピング | シンプルな[{t: 0.1, p: pos}, ...] |
| Typed Array | パフォーマンス | 位置にはPackedVector3Arrayを使用します。 |
| JSON/Binary | 保存 | ゴーストファイルの保存にはFileAccess.get_var()を使用します。 |
絶対にしてはいけないこと
- 超高精度が求められるレースの計時に OS.get_ticks_msec() を絶対に使用しないでください — ミリ秒単位の精度では、高品質なレースゲームには粗すぎます。マイクロ秒単位の精度を得るには、
Time.get_ticks_usec()を使用してください。 - フィニッシュラインのトリガー判定を _process() だけに絶対に頼らないでください — ラグが発生すると描画フレームがスキップされることがあります。固定された物理ステップ内で確実に検出するため、物理的なオーバーラップは必ず
_physics_process()で評価してください。 - インスタンス化の直後に Area3D のオーバーラップを絶対に評価しないでください — 物理サーバーとの同期には、少なくとも 1 回の物理フレームが必要です。プレイヤーを確認する前に
await get_tree().physics_frameを実行してください。 - チェックポイントの CollisionShape3D を不均一に拡大縮小しないでください — 基盤となる SAT 衝突判定の計算が壊れます。代わりに、内部のシェイプリソース(例:
BoxShape3D.size)を必ず拡大縮小してください。 - マルチプレイヤーレースで位置の同期に TCP(信頼性あり)を絶対に使用しないでください — 混雑制御アルゴリズムにより、大きなスパイクが発生します。高頻度の位置更新には、
TRANSFER_MODE_UNRELIABLEを指定したENetMultiplayerPeerを使用してください。 - クライアント側のフィニッシュライン通過やラップ通過を絶対に信用しないでください — 不正行為を防ぐため、
multiplayer.is_server()を使用して、権威あるサーバー側で必ずトリガーを検証してください。 - レコードのラップタイムに標準の浮動小数点数の等価比較(==)を絶対に使用しないでください — 累積時間変数での精度低下を考慮するには、
is_equal_approx()を使用してください。 - 入力バッファーをフラッシュせずに入力チェックをハードコードしないでください — フレーム単位で正確なブーストや停止の応答を得るには、
Input.flush_buffered_events()を呼び出して、エンジンが最新の生入力を処理済みであることを確認してください。 - 高速なパス追従ループ内で新しい Vector3 配列を絶対に割り当てないでください — ガベージコレクターが起動します。連続したメモリブロックを維持するには、
PackedVector3Arrayを使用してください。 - 負荷の高いループ内で動的な文字列パス($"../Checkpoint")を絶対に使用しないでください — 検索に時間がかかります。初期化時にノード参照をキャッシュするには、
@onreadyを使用してください。 - ゴースト用にプレイヤーオブジェクト全体を絶対に記録しないでください — 記録するのは基本的なトランスフォーム(位置/回転)のみです。オブジェクト全体の記録はメモリを大量に消費し、視覚的なゴーストには不要です。
- ゴーストに絶対に衝突判定を与えないでください — プレイヤーの走行ラインを妨げないよう、ゴーストは純粋な視覚的インジケーター(例:半透明)にしてください。
- チェックポイントの順序を絶対に無視しないでください — プレイヤーがフィニッシュラインに到達したかどうかを確認するだけでは不十分です。すべての中間チェックポイントを正しい順序で通過したことを検証してください。
- モニタリングを最適化せずに Area3D を絶対に使用しないでください — 物理的なオーバーラップ計算の数を最小限に抑えるため、チェックポイントが確認するのは
Player物理レイヤーのみとしてください。 - ゴーストの回転に標準の lerp を絶対に使用しないでください — ジンバルロックを避け、滑らかな回転補間を実現するには、
slerp()またはQuaternion.slerp()を使用してください。
利用可能なスクリプト
必須:ゴールデンパスの順序に従ってください。該当する段階のコーディングを始める前に、一覧にある各スクリプトを読んでください。
ゴールデンパス(必須)
time_trial_manager.gd— マイクロ秒(Time.get_ticks_usec)または物理フレームクロック。pass_checkpointは物理オーバーラップ/Area シグナルからのみ呼び出します。- チェックポイント Area — マネージャーの順序付きインデックス(
_processではなく物理フレームを使用) ghost_recorder.gd— Quaternion 回転を使用して{t, p, q}をサンプリングします。ghost_replayer.gd— 位置のlerp+ Quaternion のslerp(Euler の lerp は使用禁止)time_trial_leaderboard_bridge.gd— 整数の usec/msec を UI 文字列に変換します。
スクリプト一覧
time_trial_patterns.gd
マイクロ秒単位の計時、サーバー権威の検証、ラバーバンディング AI、フレーム単位で正確な入力バッファーのフラッシュを含む、エキスパート向けの 10 パターンです。
time_trial_manager.gd
中央クロックです。Time.get_ticks_usec()(または物理フレーム数)を累積します。フィニッシュ判定は物理オーバーラップから行う必要があります。
ghost_recorder.gd
Quaternion の "q" フィールドを含むトランスフォームのサンプルをキャプチャし、slerp に安全な再生を実現します。
ghost_replayer.gd
レコーダーと併用必須です。位置の lerp + Quaternion.slerp でサンプルを再生します。
time_trial_playback_buffer.gd
ネットワークストリーミング中にゴーストを滑らかに再生するためのジッターバッファーです。
time_trial_leaderboard_bridge.gd
生のタイムデータを人間が読みやすい文字列に変換するフォーマットユーティリティです。
エキスパート向けタイムトライアルのパターン
1. ゴーストの差分圧縮
位置/回転がしきい値を超えて変化した場合にのみ、キーフレームを保存します。FileAccess.open_compressed() と ZSTD を使って永続化し、JSON よりもバイナリ浮動小数点数を優先します。
2. リーダーボードブリッジ
記録は int のマイクロ秒/ミリ秒で保存します。安定した UI 表示のために %02d:%02d.%03d でフォーマットします(例:01:24.450)。
エキスパート向け知識(必要に応じて)
LLM が知らないことに関するルール: 一般的なエージェントが読む前には知らない情報であれば、リファレンスを読み込みます。エキスパート向けの差分を削除してはいけません。
- time-trial-expert-patterns.md — 復元された基本的な解説(アーキテクチャ、理由、実装の詳細)
リファレンス
段階的な情報開示:特定の API を調査する場合にのみ公式ドキュメントへのリンクを開き、関連スキルは関連分野に進む場合に読み込みます。全体をあらかじめ読み込んではいけません。
公式ドキュメント
- Time —
OS.get_ticks_msec()ではレース記録に粗すぎる場合に、マイクロ秒単位のラップタイム計測にget_ticks_usec()を使用します。 - アイドル処理と物理処理 — 負荷時に描画フレームがスキップされる可能性があるため、フィニッシュラインとチェックポイントの重なり判定を、視覚的な
_processフレームではなく_physics_processで実行する理由を説明します。 - Area3D — すべての物理ボディをスキャンせずに順序付きチェックポイントゲートを実現するための、監視、衝突マスク、
body_enteredについて説明します。 - 衝突形状(3D) — ゲートで SAT を有効な状態に保つため、
CollisionShape3Dの不均一なスケールではなく、形状リソース(BoxShape3D.size)をスケーリングします。 - トランスフォームの使用 — ゴーストサンプルのグローバル位置/基底の取得と、オイラー角のみで保存する場合に再生時の変換へ注意が必要な理由を説明します。
- Quaternion — キーフレーム間で
slerp()を使うことで、単純なオイラー角の線形補間によるジンバルロックを避け、ゴーストの向きを補間します。 - Transform3D — 順序付きフレーム間でジッターバッファーを使ってネットワーク上のゴーストを再生するには、
interpolate_with()を使用します。 - ゲームの保存 — ゴーストの走行データやベストタイムの辞書を、浮動小数点数の表示変換による誤差なしで永続化するための
FileAccess/store_varパターンについて説明します。 - ハイレベルマルチプレイヤー — クライアントがラップやフィニッシュラインの通過を偽装できないよう、サーバー権限による RPC 検証を行います。
- MultiplayerPeer — TCP のような信頼性が遅延の急増を招く、高頻度のレーサートランスフォームには
TRANSFER_MODE_UNRELIABLEを使用します。 - Input — フレーム単位で正確なブースト/停止処理を物理ステップ前に最新の生入力と同期する必要がある場合は、
flush_buffered_events()を使用します。 - Engine — 整数のフレーム数による計測を MM:SS.mmm UI に変換するには、
physics_ticks_per_second/get_physics_frames()を使用します。
関連スキル
前提条件
- godot-project-foundations — トラックシーンに
TimeTrialManagerとチェックポイント Area を組み込む前に、シーンツリー、オートロード、リソースの配置を確認します。 - godot-physics-3d — チェックポイントの順序を確実にする、Area3D/CollisionShape3D のレイヤー、RigidBody/CharacterBody の車両、物理フレームでの重なり判定ルールについて説明します。
- godot-signal-architecture — 壊れやすいノードパスへの依存を避けながら、ゲート、マネージャー、HUD、ゴーストシステム間で型付きのラップ/スプリット/フィニッシュシグナルを使用します。
- godot-gdscript-mastery — タイミングと権限のパターンで使用する型付き配列、Packed* バッファー、
await physics_frame、RPC アノテーションについて説明します。
補完
- godot-input-handling — タイムトライアルの NEVER ルールで物理処理の前にフラッシュする必要がある、アクションマップとバッファー処理されたブースト/ステア入力について説明します。
- godot-save-load-systems — メモリー内のサンプル配列だけでなく、圧縮されたバイナリのゴーストファイルとベストタイムの永続化について説明します。
- godot-multiplayer-networking — ライブレースやストリーミングされるゴーストフレームに使用する ENet ピア、権限、信頼性の低いトランスフォーム同期について説明します。
- godot-adapt-single-to-multiplayer — ソロのタイムトライアルをオンラインレースに発展させる際の、ラグ補償、スナップショット、関心パターンについて説明します。
- godot-navigation-pathfinding — 衝突判定を不正に操作せずにプレイヤーのペースに合わせるラバーバンド AI に使用する、NavigationServer3D エージェントの最大速度について説明します。
- godot-monte-carlo-balancer — トライアルのパラメーターをリリースする前に、ラバーバンド係数、チェックポイントの難易度、目標クリアタイムをシミュレーションします。
- godot-camera-systems — 再生中に走行中の車と衝突しないゴーストのビジュアルを追跡する必要がある、追跡/リプレイカメラについて説明します。
下流/利用側
- godot-genre-racing — チェックポイントの計時、ゴースト、リーダーボードの書式設定をコアループの基本要素として利用する、レーシングジャンル全体のスタックです。
- godot-game-loop-collection — このスキルで検証されたベストタイムをアンロック条件にできる、メタなインベントリー/コレクションループについて説明します。
マスター
- godot-master — スキル横断での検索に使用する、ライブラリルーター兼ミラー化されたモジュールエントリーです。