mcpField
G
godot-master

godot-master

github.com/thedivergentai開発9075.0k 回インストール2 週間前に更新
リポジトリ

godot-master について

godot-masterは、Godot 4.7+で開発するアーキテクトや開発者向けのナレッジハブです。アーキテクチャの判断フレームワークや実践ワークフロー、エンジン機能とゲームジャンル別の設計指針を提供し、移行履歴としては扱いません。

主な機能

  1. 01Godot 4.7+のアーキテクチャ指針
  2. 02状態の所有権とシグナル設計
  3. 03状況別のアーキテクチャ判断
  4. 04プロジェクト構築ワークフロー
  5. 05システム横断・ジャンル別パターン

活用シーン

  1. 01Godotプロジェクトの構成を計画
  2. 02モジュール型エンティティと状態遷移の設計
  3. 03ゲームジャンルに応じたシステム選択
  4. 04Godot CLIビルダーを使ったプロジェクト構築

インストール

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

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

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
2d-animation-cutout-and-skeletal.md
2d-animation-expert-techniques.md
2d-animation-migration-notes.md
2d-animation-signals-and-frame-events.md
2d-animation.md
2d-physics-area2d-and-queries.md
2d-physics-collision-layers-masks.md
2d-physics-migration-notes.md
2d-physics.md
3d-lighting-environment-and-fog.md
3d-lighting-gi-and-bake-recipes.md
3d-lighting-migration-notes.md
3d-lighting.md
3d-materials-migration-notes.md
3d-materials-pbr-workflows.md
3d-materials.md
3d-world-building-gridmap-and-csg.md
3d-world-building-migration-notes.md
3d-world-building-streaming-and-procgen.md
3d-world-building.md
ability-system-elite-ability-patterns.md
ability-system-migration-notes.md
ability-system.md
adapt-2d-to-3d-migration-notes.md
adapt-2d-to-3d-migration-recipes.md
adapt-2d-to-3d.md
adapt-3d-to-2d-dimension-reduction.md
adapt-3d-to-2d-migration-notes.md
adapt-3d-to-2d.md
adapt-desktop-to-mobile-migration-notes.md

詳細

Godot Master:リードアーキテクト向けナレッジハブ

すべてのセクションは、ナレッジの差分、つまりベースモデルがすでに知っていることと、実際の製品を出荷してきたシニア Godot エンジニアが知っていることのギャップに焦点を当てることで、そのトークンに見合う価値を提供します。

ライブラリの対象 — Godot 4.7+

すべてのドメインスキルのミラーは Godot 4.7+(安定版)を対象とします。エンジンのバージョンアップグレード(1.x/2.x のレガシー版 → 3 → 4 → 4.x の段階的アップグレード)には、godot-version-migration を使用してください。このハブを移行履歴として扱わないでください。

各機能へ案内する際に留意すべき 4.7 の横断的な注意事項:AreaLight3D/HDR → 3D ライティング;Asset Store と Asset Library の違い → エクスポート/プラットフォームモジュール;RichTextLabel の ImageUnit、入力デバイス ID 定数、Jolt の挙動 → 移行ハブのモジュールノート。


🧠 パート 1:エキスパートの思考フレームワーク

「誰が何を所有するのか?」 — アーキテクチャの健全性チェック

システムを書く前に、状態の各要素について、次の 3 つの質問に答えてください。

  • データを所有するのは誰か?(CombatSystem ではなく、StatsComponent が体力を所有する)
  • 変更を許可されているのは誰か?(apply_damage() のような公開メソッドを介して、所有者だけが変更できる)
  • 変更されたことを知る必要があるのは誰か?(health_changed シグナルをリッスンしているすべての人)

すべての状態変数についてこの 3 つすべてに答えられない場合、アーキテクチャには結合の問題があります。これは OOP のカプセル化ではありません。Godot 固有の考え方です。なぜなら、アクセス修飾子ではなく、シグナルシステムそのものが強制の仕組みだからです。

Godot の「レイヤーケーキ」

すべての機能を 4 つのレイヤーに整理してください。シグナルは上方向にのみ伝わり、下方向には伝わりません。

┌──────────────────────────────┐
│  PRESENTATION (UI / VFX)     │  ← Listens to signals, never owns data
├──────────────────────────────┤
│  LOGIC (State Machines)      │  ← Orchestrates transitions, queries data
├──────────────────────────────┤
│  DATA (Resources / .tres)    │  ← Single source of truth, serializable
├──────────────────────────────┤
│  INFRASTRUCTURE (Autoloads)  │  ← Signal Bus, SaveManager, AudioBus
└──────────────────────────────┘

重要なルール:プレゼンテーションはデータを直接変更してはなりません。インフラストラクチャはシグナルのみを介してやり取りします。Label ノードが player.health -= 1 を呼び出しているなら、アーキテクチャは破綻しています。

シグナルバスの階層型アーキテクチャ
  • グローバルバス(Autoload):ライフサイクルイベント(match_started、player_died、settings_changed)にのみ使用します。デバッグの煩雑化が代償となるため、イベント数は 15 未満に抑えてください。
  • スコープ付き機能バス:各機能フォルダーに専用のバスを設けます(例:CombatBus は戦闘ノード専用)。これが、規模を拡大できる折衷案です。
  • 直接シグナル:単一シーン内の親子間の通信に使用します。シーンの境界を越えて使用してはいけません。
🔗 「スマートな相互接続」の指針

エキスパートシステムは、孤立していることではなく、ペイロードの合成によって定義されます。

  • 物理演算 → パフォーマンス:PhysicsServer2D と RenderingServer は、SceneTree のノードによるオーバーヘッドを回避します。1,000 個以上の弾丸やパーティクルを扱う場合に使用すると、O(1) の処理を実現できます。
  • アニメーション → 物理演算:AnimationTree.get_root_motion_position() は、アニメーションによる変位を物理演算の velocity に変換し、複雑な移動時の「足滑り」を防ぎます。
  • データ → リアクティビティ:シリアライズされた Resource オブジェクト(Stats など)は、変更時にシグナルを発行するため、密結合を避けながら UI を自動的に更新できます。
  • アセット → 生成:ResourceLoader の非同期フェーズ中にプリロードする O(1) の Dictionary ベースのキャッシュにより、アイテムや敵の生成時に発生する I/O のひっかかりを防ぎます。
  • モバイル → ビジュアル:ロード画面中に非表示のエフェクトをインスタンス化して GPU シェーダーパイプラインのコンパイルを強制し、実行時のフレームのひっかかりを防ぎます。
  • ネットワーク → 帯域幅:パケットを 100 バイト未満に保つため、同期には JSON/文字列ではなく、PackedByteArray へのビットパッキングを使用します。
  • ジャンルの合成:
    • Shooter:100 倍のパフォーマンスを得るため、RayCast3D ノードではなく、必ず intersect_ray()(直接空間状態)を使用します。
    • RPG:エンドゲームの進行を維持するため、ダメージは base * pow(scaling, level) に従います。
    • RTS:隊形の整合性を保つため、Relative Offset を使って重心を基準にグループを移動させます。
    • Metroidvania:シームレスなルーム切り替えには ResourceLoader.load_threaded_request() を使用します。
    • Platformer:プロフェッショナルな操作感を実現するには、Jump Buffering(約 0.15 秒)と Coyote Time が必須です。
    • Simulation:Tick Manager でバッチ処理を行います。数千のユニットを維持するには、エンティティごとの _process を避けてください。
    • Romance:複雑な物語の分岐を表現するため、Multi-Axial Affection(魅力、信頼、安心感)を使用します。
    • Architecture:シーン間の循環結合をなくすため、Signal Architecture は「シグナルは上へ、呼び出しは下へ」という原則に厳密に従います。

🧭 パート 2:アーキテクチャ上の意思決定フレームワーク

マスター意思決定マトリクス
シナリオ戦略必須スキルチェーントレードオフ
迅速なプロトタイプイベント駆動型モノリス読む:基礎 → オートロード。ジャンルやプラットフォームのリファレンスは読み込まないでください。すぐに着手できますが、スパゲッティ化のリスクがあります
複雑なRPGコンポーネント駆動型読む:コンポジション → 状態 → RPGステータス。マルチプレイヤーやプラットフォームのリファレンスは読み込まないでください。初期設定は大変ですが、無限に拡張できます
大規模なオープンワールドリソースストリーミング読む:オープンワールド → セーブ/ロード。パフォーマンスも読み込みます。I/Oが複雑で、10Kユニットを超えると浮動小数点精度による揺れが発生します
サーバー認証型マルチプレイヤー決定論的読む:サーバーアーキテクチャ → マルチプレイヤーネットワーク。シングルプレイヤー向けジャンルのリファレンスは読み込まないでください。レイテンシーが高くなりますが、チート対策を強化できます
モバイル/Webへの移植アダプティブ・レスポンシブ読む:UIコンテナー → デスクトップからモバイルへの適応 → モバイルプラットフォーム。UIは複雑になりますが、幅広いユーザーに届けられます
アプリケーション/ツールアプリコンポジション読む:アプリコンポジション → テーマ設定。ゲーム固有のリファレンスは読み込まないでください。ゲームとは異なるパラダイムです
恋愛/恋愛シミュレーション好感度の経済設計読む:恋愛 → 会話 → UIリッチテキスト。UI/ナラティブの密度が高くなります
秘密/イースターエッグ意図的な難読化読む:秘密 → 永続化。コミュニティの活性化につながりますが、デバッグのリスクがあります
収集クエスト探索者ロジック読む:収集要素 → Marker3Dの配置。プレイヤーの定着と探索意欲につながります
季節イベント実行時の差し込み読む:イースターのテーマ設定 → マテリアルの切り替え。すばやくブランドを反映でき、アセットを汚しません
ソウルライクの死と復活リスクと報酬を伴う復活読む:復活/遺体回収 → 3D物理。緊張感を高められますが、プレイヤーを苛立たせるリスクがあります
ウェーブ制アクション戦闘ペーシングループ読む:ウェーブ → 戦闘。緊張感を高め、遭遇を設計できます
バランス/難易度/経済のペーシングモンテカルロ・バランスラボ読む:リソース → 経済 → 戦闘/RPGステータス/ウェーブ(必要に応じて) → モンテカルロ・バランサー → テスト → ビルダー。統計的な厳密さを得られます。抽象シミュレーションはヘッドレスGodotと照らし合わせて調整する必要があります
サバイバル経済採集ループ読む:採集 → インベントリ。リソースの希少性とループの継続性を実現します
レース/スピードラン検証ループ読む:タイムトライアル → 入力バッファ → レースジャンル。高い精度を実現し、ゴースト記録がプレイ意欲を高めます
ホラー/ステルス緊張感の管理読む:ホラージャンル → ステルスジャンル → オーディオ。雰囲気を作り、プレイヤーの無防備さを演出します
カード/ボードゲームルールの適用読む:カードゲームジャンル → ターンシステム。状態が決定論的になる一方、UIの比重が大きくなります
シミュレーション/RTSバッチ処理読む:シミュレーションジャンル → RTSジャンル → パフォーマンス。大量のユニットに対応し、O(1)のロジックを実現します
HDR/シネマティックなビジュアルディスプレイパイプライン読む:3Dライティング → デスクトッププラットフォーム → シェーダーの基礎。プロジェクト設定でビューポートHDRを有効にします。プラットフォームごとのトーンマッピング調整が必要です
長方形のエリアライトAreaLight3D読む:3Dライティング → 3Dマテリアル。発光+GIのハックよりAreaLight3Dを優先します。最高品質で使用するにはForward+レンダラーが必要です
モバイルのタッチ操作ネイティブジョイスティック読む:モバイルプラットフォーム → デスクトップからモバイルへの適応。組み込みの仮想ジョイスティック(4.7+)を使用します。プラグインへの依存を抑えられます
アドオン/アセットの検索アセットストア読む:プロジェクトの基礎 → ビルドのエクスポート。アセットストアがアセットライブラリに代わります。ストアのUIはベータ版のため、アドオンごとにライセンスを確認してください
エージェントの視覚確認/ビジュアルQAキャプチャ → WebP → 評価基準読む:エージェントの視覚機能。スクリーンショットのアセット、ウィンドウ/領域/画面、または一時的なエディターブリッジを使って、構造化レビューを行います。ジャンルのリファレンスは読み込まないでください。ホスト側のみで使用し、オートロードにしないでください/ステージングしたアドオンを残さないでください
アーティファクト → Godotプロジェクト台帳の後にスタブ読む:GDAS-reader → REA。スタブで指定されるまでは、ジャンルのリファレンスを読み込まないでください。スタブのみを作成し、不明な動作はpassのままにします
「ノードを使わない」判断

専門家だけが行う、最も影響の大きい判断のひとつです。Godot のドキュメントでは、「あらゆるものにノードを使うのは避ける」よう明確に示されています。

種類使用する場面コスト専門家向けのユースケース
Objectカスタムデータ構造、手動のメモリ管理最軽量です。.free() を手動で呼び出す必要があります。カスタム空間ハッシュマップ、ECS のようなデータストア
RefCounted一時的なデータパケット、自動削除されるロジックオブジェクト参照がなくなると自動的に削除されます。DamageRequest、PathQuery、AbilityEffect — シーンツリーを必要としないロジックパケット
ResourceInspector に対応したシリアライズ可能なデータRefCounted より少し重くなります。.tres の入出力を処理します。ItemData、EnemyStats、DialogueLine — デザイナーが Inspector で編集するデータ全般
Node_process/_physics_process が必要、シーンツリー内に存在する必要がある最も重くなります — ノードごとに SceneTree のオーバーヘッドが発生します。フレームごとの更新や空間トランスフォームが必要なエンティティのみに使用します

専門家向けのパターン:すべてのロジックパケットとデータコンテナに RefCounted のサブクラスを使用します。空間ツリー内に存在する必要があるものだけに Node を使用します。これにより、複雑なシステムのシーンツリーのオーバーヘッドを半減できます。


🔧 パート 3:コアワークフロー

ワークフロー 1:プロフェッショナルなスキャフォールディング

空のプロジェクトから、本番環境に対応したコンテナまで。

必須 — ファイル全体を読むこと:基礎

  1. クラスの種類別ではなく、機能別(/features/player/、/features/combat/)に整理します。player/ フォルダーには、プレイヤー用のシーン、スクリプト、リソース、テストをまとめます。
  2. 読むこと:シグナルアーキテクチャ — イベント数を 15 未満に抑えた GlobalSignalBus オートロードを作成します。
  3. 読むこと:GDScript の習得 — Project Settings → GDScript → Debugging で untyped_declaration 警告を有効にします。
  4. ベースとなる .gitignore、エクスポートプリセット、入力マップには、**プロジェクトテンプレート**を適用します。
  5. Godot CLI 経由でシーン階層をプログラムから生成するには、Builder(builder_create_scene.py、builder_add_node.py、builder_save_scene.py)を使用します。

注意

ワークフロー 1 で絶対にしないこと

  • 絶対にロジックスクリプトで res:// パスを使用しないでください。リソースを移動しても有効な状態を保てるよう、@export_file または @export_dir を使用してください。
  • 絶対に_init() で子ノードを初期化しないでください。シーンツリーの準備ができていません。_ready() または @onready を使用してください。
  • 絶対にPhysics Ticks のプロジェクト設定を「Default」のままにしないでください。一貫性を保つには 60 に設定するか、適応型ロジックには Engine.physics_ticks_per_second を使用してください。
  • デバッグに 絶対に_process() 内で print() を使用しないでください。フレーム時間の急増を避けるため、Debugger または push_error() を使用してください。

スキャフォールディング中は、戦闘、マルチプレイヤー、ジャンル、プラットフォームのリファレンスを読み込まないでください。

ワークフロー 2:エンティティのオーケストレーション

モジュール化され、テスト可能なキャラクターを構築します。

必須の順序 — すべて読むこと:Composition → State Machine → CharacterBody2D または Physics 3D → Animation Tree エンティティの作業では、UI、Audio、Save/Load のリファレンスを読み込まないでください。

  • ステートマシンは InputComponent に問い合わせます。入力を直接処理することはありません。これにより、リファクタリングなしで AI とプレイヤーを切り替えられます。
  • ステートマシンが処理するのは遷移のみです。ロジックはコンポーネントに配置します。MoveState が MoveComponent に動作するよう指示し、その逆にはしません。
  • すべてのエンティティはF6 テストに合格する必要があります。「現在のシーンを実行」(F6)を押してもクラッシュしないことを確認してください。クラッシュする場合、そのエンティティにはシーン外部の依存関係があります。

注意

ワークフロー 2 で絶対にしてはいけないこと

  • 絶対に parent.do_thing() を呼び出さないでください。親が変更されると、エンティティが壊れます。代わりにシグナル request_action を発行してください。
  • 絶対に移動に _process を使用しないでください。可変リフレッシュレートのモニターでのちらつきを避けるため、_physics_process を使用してください。
  • 絶対にアニメーション名をハードコードしないでください。AnimationPlayer で簡単に名前を変更できるよう、StringName 定数または Resource マップを使用してください。
  • 絶対に絶対パスで get_node() を使用しないでください。ツリーのリファクタリングに耐えられるよう %UniqueName を使用してください。
ワークフロー 3:データ駆動型システム

リソースを介して Combat、Inventory、Stats を連携させます。

必須の順序 — すべて読むこと:Resource Patterns → RPG Stats → Combat → Inventory

  • Resource を継承する ItemData.gd を 1 つ作成します。スクリプトを 100 個作る代わりに、これを 100 個の .tres ファイルとしてインスタンス化します。
  • HUD は Player を直接参照しません。Signal Bus 上の player_health_changed をリッスンします。
  • すべての @export Resource 変数で「Local to Scene」を有効にするか、_ready() で resource.duplicate() を呼び出してください。これを怠ると、Part 8 の Bug #1 の原因になります。

注意

ワークフロー 3 で絶対にしてはいけないこと

  • 絶対にSignal Bus で Node の参照を渡さないでください。オブジェクトは解放されるため、長期的な追跡には RID または ID のほうが安全です。
  • 絶対に実行時にコードから .tres ファイルを変更しないでください(ディスク上のファイルが変更されます)。変更前に必ず .duplicate() を使用してください。
  • 絶対に検索頻度の高い処理に Array を使用しないでください。O(1) で検索できる StringName キーの Dictionary を使用してください。
  • 絶対にアイテム数や正確なリソース管理に float を使用しないでください。int を使用し、表示用にスケーリングしてください。
ワークフロー 4:永続化パイプライン

必須:Autoload Architecture → Save/Load → Scene Management

  • Dictionary マッピングを使用してシリアライズします。新しいフィールドを追加しても古いセーブファイルが壊れないよう、.get("key", default_value) を使用してください。
  • プロシージャルワールドでは、マップ全体ではなく Seed と変更内容の Delta-List を保存します。100MB のワールドを 50KB のセーブデータにできます。

注意

ワークフロー 4 で絶対にしてはいけないこと

  • 絶対に Object や Node のインスタンス全体を保存しないでください。一時的なポインターが含まれています。データを Dictionary またはカスタム Resource に抽出してください。
  • 厳密な型付けが必要なデータ(例:Vector2)に 絶対に JSON を使用しないでください。構造化された Godot 型には var_to_bytes または ConfigFile を使用してください。
  • オートセーブのためにメインスレッドを絶対にブロックしないでください。大きな Dictionary のシリアライズには Thread または WorkerThreadPool を使用してください。
  • エクスポート済みプロジェクトで res:// に絶対に保存しないでください。永続データには必ず user:// を使用してください。
ワークフロー 5:パフォーマンスの最適化

必須:デバッグ/プロファイリング → パフォーマンスの最適化

診断を優先するアプローチ(決して闇雲に最適化しないでください):

  1. スクリプトの処理時間が長い → 組み込みの Profiler でプロファイリングします。何百ものノードで _process が呼び出されていないか確認します。単一マネージャーパターンまたは Server API に切り替えます(Part 6 を参照)。
  2. ドローコールが多い → 繰り返しのジオメトリには MultiMeshInstance を使用します。ORM テクスチャでマテリアルをバッチ化します。
  3. 物理演算によるカクつき → コリジョンをプリミティブ形状に簡略化します。2D Physics または 3D Physics を読み込みます。移動処理に _physics_process ではなく _process を使用していないか確認します。
  4. VRAM の過剰使用 → テクスチャを VRAM 圧縮に切り替えます(デスクトップでは BPTC/S3TC、モバイルでは ETC2)。PNG を未圧縮のまま出荷してはいけません。
  5. 断続的なフレームスパイク → 通常は GC パス、同期的な load()、または NavigationServer の再計算が原因です。ResourceLoader.load_threaded_request() を使用します。

注意

ワークフロー 5 の禁止事項

  • 決して _process 内で get_nodes_in_group() を使用しないでください。毎フレーム O(n) の処理が発生します。配列を _ready() でキャッシュしてください。
  • 決して「Stay」ロジックに Area2D シグナルを使用しないでください。定期的に get_overlapping_bodies() を呼び出すか、マネージャーレベルで PhysicsServer のチェックを使用してください。
  • 決してプロファイリングの前に最適化しないでください。ドローコールが 2000 回あり GPU の処理を妨げているなら、スクリプトの 1ms は問題ではありません。
  • ホットパスでは決して load() を使用しないでください。必ず preload を使用するか、非同期読み込みには ResourceLoader を使用してください。
ワークフロー 6:クロスプラットフォーム対応

必須:入力処理 → デスクトップからモバイルへの対応 → モバイルプラットフォーム 必要に応じて以下も読む:デスクトッププラットフォーム、Web プラットフォーム、コンソールプラットフォーム、VR プラットフォーム。

  • すべての入力タイプを正規化されたアクションに変換する InputManager オートロードを使用します。Input.is_key_pressed() を直接読み取ってはいけません。コントローラーとタッチに対応できなくなります。
  • モバイルのタッチターゲット:物理サイズで最低 44px にします。ノッチや切り欠きのあるデバイスでは、Safe Area のロジックとともに MarginContainer を使用します。
  • Web エクスポート:Godot の AudioServer は最初の再生前にユーザー操作を必要とします(ブラウザーのポリシーによる制約です)。「クリックして開始」画面で対応します。

注意

ワークフロー 6 の禁止事項

  • 決して機能の検出に OS.get_name() を使用しないでください。「SteamDeck」のようなサブセットに対応するには、OS.has_feature("mobile") またはカスタム機能タグを使用します。
  • 決して特定のアスペクト比を前提にしないでください。必ず Anchor ノードと組み合わせて Expand または Keep Aspect を使用します。
  • 決してGLES3/Compatibility の代替パスなしで、デスクトップ専用シェーダー(複雑な深度サンプリングなど)をモバイル/Web で使用しないでください。
  • デスクトップビルドで physical_keycode を無視してはいけません。これにより、キーボード配列(AZERTY/QWERTY)が移動操作に影響しないようにできます。
  • サニタイズされていない文字列を決して JavaScriptBridge.eval() に渡さないでください。これにより、Web ビルドでのスクリプトインジェクションを防げます。sanitize_js_string() ヘルパーを使用してください。
ワークフロー 7:プロシージャル生成

必須:プロシージャル生成 → タイルマップを極める または 3D ワールド構築 → ナビゲーション

  • 決定論的な生成を行うため、固定の seed を設定した FastNoiseLite リソースを必ず使用してください。
  • メインスレッドで NavMesh をベイクしないでください。NavigationServer3D.parse_source_geometry_data() と NavigationServer3D.bake_from_source_geometry_data_async() を使用してください。
  • 無限ワールドでは、チャンクの読み込みは必ず WorkerThreadPool を使用してバックグラウンドスレッドで行ってください。シーンのチャンクをツリー外で構築し、メインスレッドで add_child.call_deferred() を呼び出してください。

注意

ワークフロー 7:絶対にしてはいけないこと

  • 「背景」のノイズに対して、ノードを絶対にインスタンス化しないでください。数千個の小さなディテールには、MultiMeshInstance または _draw 内の描画ループを使用してください。
  • 1つの変更のためにマップ全体を絶対に再生成しないでください。実際に変更された部分だけを更新する「ダーティチャンク」システムを使用してください。
  • concave_polygon_shape を使用する場合、メッシュ生成と同じフレームにコリジョンを絶対に配置しないでください。物理スレッドが停止します。
  • すべてのユニットについて、パス検索を毎フレーム絶対に実行しないでください。target_position をタイマーで更新する NavigationAgent を使用してください。
ワークフロー 8:マルチプレイヤーアーキテクチャ

必須 — 読んでください:シングルプレイヤーからマルチプレイヤーへ → ネットワーキング → サーバーアーキテクチャ シングルプレイヤーのジャンル別ブループリントは読み込まないでください。

  • クライアントは入力を送り、サーバーは結果を計算します。クライアントがダメージ、位置の差分、インベントリの変更を決定することは絶対にありません。
  • サーバーによる再同期を伴うクライアントサイド予測を使用してください。ローカルで予測し、サーバーのスナップショットに基づいて修正します。最大約 150ms のレイテンシを隠蔽できます。
  • Godot 4 では、MultiplayerSpawner がレプリケーションを処理します。グローバルではなく、シーンごとに設定してください。

注意

ワークフロー 8:絶対にしてはいけないこと

  • 検証せずに rpc_id(1, ...)(クライアントからサーバー)を絶対に信頼しないでください。ハッキングされたクライアントは damage = 999999 を送信できます。
  • _process のトランスフォームを直接絶対にレプリケーションしないでください。Input ベクトルをレプリケーションし、両側で移動をシミュレートしてください。
  • 高頻度パケット(移動)に TCP を絶対に使用しないでください。UDP/ENet を使用し、補間でパケットの損失に対処してください。
  • すべての投射物を絶対に同期しないでください。ビジュアルにはクライアントサイド予測を使用し、「発射」イベントのみを RPC で送信してください。
  • ReflectionProbe、VoxelGI、SDFGI の比較:プローブは低コスト/静的、VoxelGI は中程度のコスト/ベイク済み、SDFGI は高コスト/動的です。プラットフォームの予算に応じて選択してください(パート 5 を参照)。
ワークフロー 9:レスポンシブ UI とエキスパート向けテーマ設定(監査済み)

必須チェーン:UI コンテナー → UI テーマ設定 → リッチテキスト → トゥイーン

  1. F6 の原則:すべての UI シーンは単独でテストできる必要があります。MOUSE_FILTER_STOP は背景にのみ使用し、子要素には PASS を使用してください。
  2. ゆとりの確保:手動で余白を設定する代わりに、add_theme_constant_override("separation", X) を使用してください。
  3. 適応型スケーリング:ブレークポイントに応じたモバイル/デスクトップの切り替えには、ui_containers_responsive_layout_builder.gd を使用してください。
  4. ライフサイクルの安全性:新しい子要素へ同じフレーム内でスクロールしないでください。scroll_vertical を変更する前に、await get_tree().process_frame を実行してください。
  5. データ統合:Resource-to-UI バインディングを使用してください。UI ノードはステートレスな投影レイヤーでなければなりません。

注意

ワークフロー 9 の禁止事項

  • 絶対に絶対ピクセルオフセットを使用しないでください。4K ディスプレイや小型のモバイル画面では UI が読めなくなります。Container のサイズ設定を使用してください。
  • 絶対にMarginContainers を深くネストしないでください。インスペクターが使いづらくなります。プロジェクト全体の余白には、単一の Theme リソースを使用してください。
  • 絶対にUI ボタンをゲームプレイロジックに直接接続しないでください。UI は「シグナル」を送信し、PlayerController が受信します。これにより、UI 削除時のクラッシュを防げます。
  • 絶対に_process() を使って UI 要素をターゲットへ移動させないでください。カクつきやフレームレートへの依存を避けるため、Tween を使用してください。
  • 絶対に透明なコンテナーの mouse_filter を STOP のままにしないでください。背後にあるすべての要素へのクリックを「奪って」しまいます。
  • 絶対にres:// プレフィックスと安全な拡張子(.tres、.res、.theme)を検証せずに、パスに対して動的な load() を使用しないでください。任意のコードやリソースの実行を防ぎます。
ワークフロー 10:シネマティックなライティングと VFX(監査済み)

必須チェーン:3D ライティング → パーティクル → 3D マテリアル → シェーダー

  1. GI の選択:屋内には VoxelGI、オープンワールドには SDFGI を使用してください。両方の範囲が重なる状態でリリースしないでください。
  2. シャドウの予算:シャドウを投影する DirectionalLight は最大 2 つまでにしてください。モバイル向けの補助光には 3d_lighting_fake_gi_bounce.gd を使用してください。
  3. VFX のライフサイクル:タイマーより finished シグナルを使用してください。非同期 GPU の停止を避けるため、restart() で再実行してください。
  4. 最適化:GPU キャッシュとテクスチャスロットを節約するため、ORM Texture パッキング(AO/ラフネス/メタル)を使用してください。
  5. バッチ処理:ドローコールのペナルティなしに何千ものインスタンスでマテリアルを変化させるには、Instance Uniforms を使用してください。

注意

ワークフロー 10 の禁止事項

  • 絶対にCollisionShape ノードをスケーリングしないでください。物理演算のジッターを避けるため、Shape Resource のみを厳密にスケーリングしてください。
  • 絶対に切り抜きメッシュ(葉やフェンス)に TRANSPARENCY_ALPHA を使用しないでください。ソートの乱れを防ぐため、ALPHA_SCISSOR を使用してください。
  • 絶対にゲームプレイ中に CSG ノードをアニメーションさせないでください。CPU による高コストなジオメトリの再計算が発生します。
  • 絶対に2D 風のゲームにリアルタイムのグローバルイルミネーション(SDFGI/VoxelGI)を使用しないでください。DirectionalLight2D と CanvasModulate を使用してください。
  • 絶対にCamera3D のニア/ファー平面を無視しないでください。不適切な設定は広大なワールドで Z ファイティングを引き起こします。
ワークフロー 11:プログラムによるシーン構築(ビルダー)

必須:ビルダー バッチ処理または複雑な手続き型の足場構築にのみ使用してください。 大規模な CLI 自動化を行う場合は、単独の godot-builder スキルを優先してください。

  1. ステップ 1:ディスクに触れる前に、ノード階層を紙または Markdown に書き出します。
  2. ステップ 2:builder_create_scene.py を使用して、ルートノードと .tscn のパスを定義します。
  3. ステップ 3:子ノードには builder_add_node.py を使用します。シリアライズで保持されるよう、すべてのノードに owner を設定します。
  4. ステップ 4:シーンが問題なく読み込まれることを確認するため、必ず builder_run_project.py または builder_launch_editor.py を呼び出します。
  5. エキスパートルール:Builder は構造(ノード、名前、継承)の構築に使用し、振る舞いの構築には GDScript を使用します。

注意

ワークフロー 11:絶対にしてはいけないこと

  • 絶対に、階層を設計せずにいきなり builder_add_node.py を実行しないでください。スパゲッティ状のシーンができてしまいます。
  • 絶対に、スクリプトやシーンのプロパティで絶対ファイルシステムパスを使用しないでください。res:// のみを使用してください。
  • 絶対に、Shape リソースを割り当てずに CollisionShape2D/CollisionShape3D を追加しないでください。ノードを追加するだけでは何も起こりません。
  • バッチでシーンを書き込んだ後、builder_run_project.py/builder_launch_editor.py による検証を絶対に省略しないでください。
セキュリティ:境界マーカーと検証

エージェントがファイルを書き込む前に、信頼できないシーン/データテキストを取り込む場合:

  1. 境界マーカー:<<<CONTEXT_START>>> と <<<CONTEXT_END>>> で分析内容を囲みます。
  2. サニタイズ:ノード名は英数字またはアンダースコアのみで構成する必要があります。パスは res:// で始まる必要があります。
  3. 検証:変更前にシーンの存在を確認します。

🚫 パート 4:エキスパートが絶対にしてはいけないこと

各ルールには、一見わかりにくい理由、つまり実際のリリース経験を通じて初めて学べることが含まれています。

  1. 決して get_tree().root.get_node("...") を使用しないでください — 絶対パスは、祖先ノードの名前変更や親の変更が一度でもあると機能しなくなります。%UniqueNames、@export NodePath、またはシグナルベースの検出を使用してください。
  2. ループ内や _process 内で決して load() を使用しないでください — 同期的なディスク読み込みは、メインスレッド全体をブロックします。小さなアセットにはスクリプトの先頭で preload() を、大きなアセットには ResourceLoader.load_threaded_request() を使用してください。
  3. 外部参照が存在する間は決して queue_free() を実行しないでください — 参照を保持している親ノードや配列は、「Deleted Object」エラーを引き起こします。_exit_tree() で参照をクリーンアップし、解放する前に null を設定してください。
  4. ゲームプレイのロジックを決して _draw() に記述しないでください — _draw() はレンダリングスレッドで呼び出されます。ゲーム状態を変更すると、_physics_process との競合状態が発生します。
  5. 1000 個以上のオブジェクトが重なり合う場合、決して Area2D を使用しないでください — 各オーバーラップチェックには O(n²) のブロードフェーズコストがかかります。弾幕パターンには ShapeCast2D、PhysicsDirectSpaceState2D.intersect_shape()、またはサーバー API を使用してください。
  6. コンポーネントから外部状態を決して変更しないでください — HealthComponent が $HUD.update_bar() を呼び出す場合、HUD を削除するとゲームがクラッシュします。コンポーネントはシグナルを発行し、リスナーが応答方法を決定します。
  7. _physics_process 内で決して await を使用しないでください — await は実行を一時停止するため、物理ステップでフレームがスキップされます。シグナルをトリガーとして、非同期処理を別のメソッドに移してください。
  8. 頻繁に実行される辞書の検索で String キーを決して使用しないでください — String のハッシュ化には O(n) かかります。O(1) のポインター比較ができる StringName(&"key")または整数の列挙型を使用してください。
  9. 解放済みオブジェクトへの Callable 参照を決して保持しないでください — クラッシュが無言で発生したり、エラーがスローされたりします。_exit_tree() でシグナルを切断するか、CONNECT_ONE_SHOT を使用してください。
  10. 1000 個以上のエンティティに _process を決して使用しないでください — _process の呼び出しごとに、ノード単位の SceneTree オーバーヘッドが発生します。データ構造体の配列を反復処理する単一の Manager._process(データ指向パターン)を使用するか、サーバー API を直接使用してください。
  11. 解放される可能性があるノードで決して Tween を使用しないでください — Tween の実行中にノードが queue_free() されると、エラーが発生します。_exit_tree() で Tween を停止するか、SceneTree にバインドしてください:get_tree().create_tween()。
  12. _process 内で RenderingServer や PhysicsServer にデータを要求しないでください — これらのサーバーは非同期で動作します。ゲッター関数を呼び出すと同期的な停止が発生し、パフォーマンスが大幅に低下します。これらの API は、頻繁に実行される処理で意図的に書き込み専用として設計されています。
  13. 初期化順序のバグを取り繕うために call_deferred() を決して使用しないでください — アーキテクチャ上の問題(ツリー順序への依存)を隠してしまいます。明示的な初期化シグナルまたは @onready を使って、実際の依存関係を解決してください。
  14. 循環するシグナル接続を決して作成しないでください — ノード A が B に接続し、B が A に接続する状態です。最初のシグナル発行時に無限ループが発生します。メディエーターパターン(シグナルバス)を使って循環を断ち切ってください。
  15. 継承を決して 3 階層より深くしないでください — 3 階層を超えると、super() の呼び出しチェーンのデバッグが非常に困難になります。代わりにコンポジション(子 Node)を使って動作を追加してください。
  16. 物理演算が多いジャンル(FPS/ARPG)では、ヒット判定や移動に決して _process を使用しないでください。フレームレートに左右されない衝突判定を実現するため、必ず _physics_process を使用してください。
  17. 永続的なゲーム状態(Health、XP、Inventory)について、クライアントを権威のある情報源として決して信頼しないでください。Server-Auth または Secure Checksums のみで処理してください。
  18. 実行時に高頻度で行うチェックには、標準の文字列を決して使用しないでください。O(n) のハッシュ化を避けるため、必ず StringName(&"active")を使用してください。
  19. ユニット数の多いゲーム(RTS/MOBA)で、RVO の回避処理を毎フレーム手動で行わないでください。NavigationAgent の内部スレッド処理に任せてください。
  20. プロシージャル生成や重い I/O のために、メインスレッドを決してブロックしないでください。必ず WorkerThreadPool に処理を委譲してください。
  21. 固有のインスタンスで使用するリソース(例:敵のステータス)では、Local-to-Scene を決して無効にしないでください。無効にすると、すべてのインスタンス間で共有メモリのバグが発生します。
  22. 通貨に float を決して使用しないでください。複雑な経済システムでの精度のずれを防ぐため、必ず整数のセント単位を使用してください。
  23. physics_frame より前に target_position を決して設定しないでください。ナビゲーションマップは _ready() 中には準備できていません。
  24. 大きな切り抜きサーフェス(葉など)に TRANSPARENCY_HASH や ALPHA を決して使用しないでください。パフォーマンスとソートのため、ALPHA_SCISSOR を使用してください。
  25. CollisionShape ノードを決してスケーリングしないでください(Node2D/3D のスケール)。予測できない物理法線やジッターを避けるため、シェイプハンドルを使用するか、リソースのサイズを変更してください。
  26. is_on_floor() が true のときに重力を決して適用しないでください。微小なジッターが発生し、床へのスナップが妨げられます。垂直速度を必ず 0 または小さな定数にリセットしてください。
  27. 動的シグナル(キャプチャするラムダ)の切断を決して忘れないでください。Godot はローカル変数をキャプチャするラムダを自動で切断できないため、解放済みオブジェクトでクラッシュが発生します。
  28. モバイルのタッチ操作にマウスイベントを決して使用しないでください。信頼性の高いマルチタッチ対応のため、必ず InputEventScreenTouch と InputEventScreenDrag を使用してください。
  29. モバイルで Forward+ レンダラーを決して使用しないでください。GPU のボトルネックやバッテリー消費を避けるため、必ず Mobile または Compatibility レンダラーを使用してください。
  30. マウスの回転量を Transform に直接決して加算しないでください。ジンバルロックや精度の低下を防ぐため、Yaw/Pitch の変数を別々に保持してください。
  31. 実行時に高頻度で行うチェックに標準の String を決して使用しないでください。O(n) のハッシュ化オーバーヘッドを避けるため、必ず StringName(&"active")を使用してください。
  32. ゲーム状態(Health、Inventory)についてクライアントを決して信頼しないでください。クライアントはアクションを提案し、サーバーが検証してブロードキャストすることで、不正行為を防ぎます。
  33. 移動の更新に Reliable RPC を決して使用しないでください。高レイテンシー環境での Head-of-Line ブロッキングを防ぐため、UnreliableOrdered を使用してください。

📊 パート 5:パフォーマンス予算(具体的な数値)

指標モバイルの目標デスクトップの目標専門家向けメモ
ドローコール数< 100(2D)、< 200(3D)< 500植生や破片には MultiMeshInstance を使用します
三角形数表示中は < 100K表示中は < 1M500K を超える場合は LOD システムが必須です
テクスチャ VRAM< 512MB< 2GBVRAM 圧縮:ETC2(モバイル)、BPTC(デスクトップ)
スクリプト実行時間フレームあたり < 4msフレームあたり < 8msホットループを Server API に移動します
物理ボディ数アクティブなものが < 200アクティブなものが < 1000大量シミュレーションには PhysicsServer の直接 API を使用します
パーティクル数合計 < 2000合計 < 10000GPU パーティクルを使用し、visibility_aabb を手動で設定します
オーディオバス数同時に < 8同時に < 32オーディオシステムのバスルーティングを使用します
セーブファイルサイズ< 1MB< 50MBプロシージャルワールドにはシード + 差分パターンを使用します
シーンの読み込み時間< 500ms< 2sResourceLoader.load_threaded_request()

⚙️ パート 6:Server API — 専門家向けのパフォーマンス向上策

これは、ほとんどの Godot 開発者が学ぶことのない知識です。シーンツリーがボトルネックになったら、Godot の低レベル Server API を使ってシーンツリーを完全に回避します。

Server API に切り替えるタイミング
  • 10K 以上の描画インスタンス(スプライト、メッシュ):Sprite2D/MeshInstance3D ノードの代わりに、RID を使って RenderingServer を使用します。
  • スクリプトからの操作を伴う弾幕系/パーティクルシステム:Area2D ノードの代わりに、PhysicsServer2D でボディを作成します。
  • 大量の物理シミュレーション:ラグドール群、破片、または流体のようなシミュレーションには、PhysicsServer3D を直接使用します。
📊 パフォーマンス比較:SceneTree と Server API

SceneTree を回避すると、ノードのライフサイクル管理、シグナルの伝播、仮想関数(_process など)の呼び出しに伴う大きな CPU オーバーヘッドを排除できます。

指標SceneTree(ノード)Server API(RID)専門家向けの理由
オブジェクト数の上限約 1,000~5,00050,000 以上SceneTree の走査コストは O(n) です。サーバーでは O(1) の RID による直接ハンドルを使用します。
メモリオーバーヘッドノードあたり約 2KB~10KBRID あたり < 200 bytesノードはツリーの状態、シグナル、インスペクターのメタデータを保持します。RID は不透明な 24 バイトのハンドルです。
CPU 時間高い(仮想関数呼び出し)最小(直接 API)ノードではインスタンスごとに _process を呼び出す必要があります。サーバーは C++ で操作をまとめて処理します。
スレッド処理メインスレッドのみ本質的にスレッドセーフほとんどの Server API はスレッドセーフです(Project Settings で有効にする必要があります)。
ガベージコレクション自動(RefCounted)手動(割り当て/解放)サーバーでは手動のライフサイクル管理(RID の作成/削除)が必要です。

専門家向けメモ:RID を使うと、未加工のデータを管理し、エンジンのコアロジックと直接やり取りできます。SceneTree の管理処理がボトルネックとなる弾幕系、大量の植生、複雑なプロシージャルシミュレーションにおいて、これは主な「切り札」となります。

RID パターン(専門家向け)

Server API は RID(Resource ID)を介して通信します。RID はサーバー側オブジェクトへの不透明なハンドルです。重要なルール:

# Create server-side canvas item (NO node overhead)
var ci_rid := RenderingServer.canvas_item_create()
RenderingServer.canvas_item_set_parent(ci_rid, get_canvas_item())

# CRITICAL: Keep resource references alive. RIDs don't count as references.
# If the Texture resource is GC'd, the RID becomes invalid silently.
var texture: Texture2D = preload("res://sprite.png")
RenderingServer.canvas_item_add_texture_rect(ci_rid, Rect2(-texture.get_size() / 2, texture.get_size()), texture)
Server を使ったスレッド処理
  • シーンツリーはスレッドセーフではありません。一方、Server API(RenderingServer、PhysicsServer)は、Project Settings で有効にすればスレッドセーフです。
  • シーンチャンク(インスタンス化 + add_child)をワーカースレッド上で構築できますが、ライブツリーに追加するには必ず add_child.call_deferred() を使う必要があります。
  • GDScript の Dictionary/Array:スレッド間の読み取りと書き込みは安全ですが、サイズ変更(append、erase、resize)には Mutex が必要です。
  • 同じ Resource を複数のスレッドから同時に読み込むことは絶対に避けてください。読み込みスレッドは 1 つだけ使用します。

🧩 パート 7:エキスパート向けコードパターン

一般的なアーキテクチャシステムやゲームプレイシステムのエキスパート向け実装です。


🔥 パート 8:Godot 4.x の落とし穴(熟練者向け)

  1. @export リソースはデフォルトで共有されます:複数のシーンインスタンスがすべて同じ Resource を共有します。_ready() で resource.duplicate() を使うか、「Local to Scene」チェックボックスを有効にしてください。これは、初心者から最も多く報告されている Godot 4 のバグです。
  2. シグナル構文はエラーなしで失敗します:connect("signal_name", target, "method")(Godot 3 の構文)はコンパイルされますが、Godot 4 では何も起こりません。signal_name.connect(callable) を使う必要があります。
  3. Tween はノードではなくなりました:create_tween() で作成され、作成元ノードのライフサイクルに紐づきます。そのノードが解放されると、Tween も消滅します。永続的な Tween には get_tree().create_tween() を使ってください。
  4. PhysicsBody のレイヤーとマスク:collision_layer は「自分が何者か」、collision_mask は「何を検出するか」です。両方を同じ値に設定すると、自分自身との衝突が発生したり、検出を見逃したりします。
  5. ホットパスでの StringName と String の違い:StringName(&"key")はポインター比較(O(1))を使います。String は文字比較(O(n))を使います。_process 内の辞書キーには、常に StringName を使ってください。
  6. @onready のタイミング:_init() の後、_ready() の実行中に処理されます。コンストラクター時のセットアップが必要な場合は _init() を使ってください。ツリーへのアクセスが必要な場合は、@onready または _ready() を使ってください。これらを混在させると、null が発生します。
  7. サーバークエリによる停止:_process 内で RenderingServer や PhysicsServer のゲッター関数を呼び出すと、パイプラインの同期フラッシュが発生します。これらのサーバーは非同期で動作するため、データを要求すると、サーバーが追いつくまでパイプライン全体が停止します。
  8. move_and_slide() の API 変更:衝突が発生したかどうかを示す bool を返します。速度は引数ではなく、プロパティになりました。move_and_slide() を呼び出す前に velocity = dir * speed を設定してください。

📂 パート 9:モジュールディレクトリ(100 の設計図)

重要

現在のワークフローに必要なモジュールのみを読み込んでください。パート 2 の判断マトリックスを使って、どの連鎖をたどるか判断してください。

アーキテクチャと基盤

基礎 | コンポジション | アプリのコンポジション | シグナル | 自動読み込み | 状態 | リソース | テンプレート | アナリスト | 監査担当 | ビルダー | GDAS-reader | REA

バージョンアップグレード(外部ハブ): godot-version-migration — 全履歴を網羅するルーター(レガシー時代、3→4 の移行、4.0→4.7 の段階的移行)。ここにはミラーされていません。

GDScript & Testing

GDScript Mastery | Testing Patterns | Debugging/Profiling | Performance Optimization

2D Systems

2D Animation | 2D Physics | Tilemaps | Animation Player | Animation Tree | CharacterBody2D | Particles | Tweening | Shader Basics | Camera Systems

3D Systems

3D Lighting | 3D Materials | 3D World Building | Physics 3D | Navigation/Pathfinding | Procedural Generation | Raycasting

Gameplay Mechanics

Abilities | Combat | Dialogue | Economy | Inventory | Questing | RPG Stats | Turn System | Audio | Scene Transitions | Save/Load | Secrets | Collections | Waves | Harvesting | Time Trials | Revival | Monte Carlo Balancer

UI & UX

UI Containers | Rich Text | Theming | Input Handling | Seasonal Theming | Agent Vision

Connectivity & Platforms

Multiplayer | Server Logic | Export Builds | Desktop | Mobile | Web | Console | VR

Adaptation Guides
ジャンル別ブループリント(網羅)

アクション RPG | シューター | FPS シューター | RTS | MOBA | ローグライク | サバイバル | オープンワールド | メトロイドヴァニア | プラットフォーマー | 格闘 | ステルス | サンドボックス | ホラー | パズル | レース | リズム | スポーツ | バトルロイヤル | カードゲーム | ビジュアルノベル | 恋愛 | シミュレーション | タワーディフェンス | 放置クリッカー | パーティー | 教育


🐛 パート 10:エキスパート向け診断パターン

「見えないノード」バグ

症状:ノードはツリー内に存在するのに、描画されません。 エキスパートの診断手順:visible プロパティ → z_index → 親の CanvasLayer が誤ったレイヤーにある → modulate.a == 0 → カメラの near クリップ面の背後にある(3D) → SubViewport.render_target_update_mode が設定されていない → CanvasItem がどの CanvasLayer にも属していない(すべての背後に描画される)。

「入力が消費される」バグ

症状:クリックやキー入力が断続的に無視されます。 エキスパートの診断:別の Control ノードが mouse_filter = STOP の状態で対象に重なっています。または、モーダルの PopupMenu が未処理の入力を消費しています。または、別のスクリプトの _unhandled_input() が get_viewport().set_input_as_handled() を呼び出しています。

「物理演算の揺れ」バグ

症状:キャラクターが表面との接触時に振動します。 エキスパートの診断:Safe Margin が大きすぎます。または、移動に _physics_process ではなく _process を使用しているため、補間が一致していません。または、スポーン時にコリジョンシェイプが重なっており、互いを押し離したままになります。

「メモリリーク」

症状:プレイ中に RAM が徐々に増加します。 エキスパートの診断:queue_free() を呼び出しているものの、Array/Dictionary 内に参照が保持されています。または、CONNECT_REFERENCE_COUNTED でシグナルを接続した後、クリーンアップしていません。Profiler の「Objects」タブを使って、孤立したインスタンスを特定してください。親を持たない Node インスタンスを検索してください。

「フレームスパイク」

症状:FPS は安定しているのに、定期的に低下します。 エキスパートの診断:GDScript の GC 処理。または、大きなリソースを同期的に load() しています。または、NavigationServer の再ベイク。または、Server API のクエリによる停止(_process 内で RenderingServer からデータを要求)。組み込みの Profiler でプロファイリングし、関数単位のスパイクを確認してください。


🚀 パート 11:クイックスタート — Unity(C#)から Godot(GDScript)へ

Unity エコシステムから移行するシニアエンジニア向けのメンタルモデルの変化です。

1. ノードと GameObject/コンポーネント

Unity では、GameObject は Components のコンテナです。Godot では、すべてが Node です。

  • Unity:GameObject + Transform + MeshFilter + Script。
  • Godot:スクリプトをアタッチした MeshInstance3D ノード(Transform と Mesh を兼ねます)。
  • エキスパート向けの転換点:ノードの合成を活用してください。「Health Component」が必要な場合は、「Health」という名前の Node または Area3D を子として追加します。ロジックのみのコンポーネントには RefCounted を使い、メモリを節約してください。
2. シーンはネストされたプレハブ

Godot に「Prefabs」がないのは、すべてのシーンがプレハブだからです。

  • シーンは別のシーン内に、何層にもわたってインスタンス化できます。
  • エキスパート向けの転換点:再利用可能なシステム(Player、Enemy、UI Button)は、それぞれ独自の .tscn ファイルにしてください。これにより、「後順走査」(親より先に子の準備が完了する)が促進されます。
3. シグナルとイベント/アクションの違い

Godot の Signal システムは、オブザーバーパターンをネイティブに実装したものです。

  • Unity:event Action OnDeath;。
  • Godot:signal died。
  • エキスパート向けの転換点:シグナルは第一級の要素です。インスペクターに表示され、動的に接続したり、エディターから接続したりできます。Unity のシングルトンマネージャーを再現するには、グローバルイベントに「シグナルバス」パターン(Autoload)を使用します。
4. ノードを拡張するスクリプト

ノードにスクリプトをアタッチすると、そのスクリプトがノードそのものになります。

  • Unity:GetComponent<MyScript>()。
  • Godot:スクリプトはノードのクラスを拡張します(例:extends CharacterBody3D)。
  • エキスパート向けの転換点:コンパイル速度の向上とエディターの補完機能を利用するには、型付き GDScript(var x: int = 5)を使用します。型がコンパイル時に判明している場合、型付き GDScript は最適化されたオペコードを使用します。
5. メモリ管理:ガベージコレクションによる停止なし

「GC スパイク」が発生することのある Unity の C# とは異なり、GDScript は参照カウントを使用します。

  • エキスパート向けの転換点:オブジェクトは参照されなくなった時点ですぐに解放されます。これにより、決定論的なパフォーマンスが得られ、大規模な Unity プロジェクトでよく見られる断続的な「カクつき」を回避できます。
6. StringNames とパフォーマンス

Unity ではパフォーマンスのために int または Enum を使用します。Godot では StringName を使用します。

  • エキスパート向けの転換点:辞書やシグナルの検索で、定数時間(O(1))のポインター比較を行うには &"name" を使用します。

参考資料

コメント