# 機能設計書 1-シーンツリー管理

## 概要

本ドキュメントは、Godot Engineにおけるシーンツリー管理機能の詳細設計を記述する。シーンツリー（SceneTree）は、ゲームエンジンの中核となるアーキテクチャであり、すべてのノードの階層構造とライフサイクルを管理する。

### 本機能の処理概要

シーンツリー管理機能は、Godot Engineにおけるノードの階層的な組織化、更新ループの制御、グループ管理、シーン切り替えを統括する中央制御システムである。

**業務上の目的・背景**：ゲーム開発において、多数のゲームオブジェクト（キャラクター、背景、UI要素など）を効率的に管理し、それらの更新処理を一貫した順序で実行する必要がある。シーンツリーは、この複雑なオブジェクト管理を階層構造により単純化し、開発者が直感的にゲームの構造を設計できるようにする。また、ポーズ機能、プロセス優先度、グループ化などの高度な制御機構を提供することで、大規模なゲームプロジェクトでも保守性の高いコードを実現する。

**機能の利用シーン**：
- ゲーム起動時のメインシーンのロードと初期化
- ゲームプレイ中の毎フレーム更新処理（process/physics_process）
- シーン間の遷移（タイトル画面からゲーム画面への切り替えなど）
- ポーズメニュー表示時のゲーム一時停止
- 特定のグループに属するノードへの一括操作（敵キャラクター全員への通知など）
- タイマーやTweenアニメーションの管理

**主要な処理内容**：
1. ルートウィンドウの管理とノード階層の構築
2. フレーム毎の処理ループ（process/physics_process）の実行
3. ノードグループの管理と一括操作
4. シーンの切り替え・リロード・アンロード
5. ポーズ/サスペンド状態の制御
6. タイマーとTweenの処理
7. 入力イベントのノードへの伝播
8. 物理補間（Physics Interpolation）の制御
9. マルチプレイヤーAPIの統合
10. デバッグ用のコリジョン/パス/ナビゲーション表示

**関連システム・外部連携**：
- RenderingServer: 物理補間とレンダリング同期
- PhysicsServer2D/3D: 物理処理の有効/無効制御
- MultiplayerAPI: ネットワーク同期
- Input: 入力イベント処理
- MessageQueue: 遅延呼び出しの処理

**権限による制御**：メインスレッドからのみ実行可能な操作（シーン切り替え、ポーズ設定など）が存在し、スレッドセーフティが考慮されている。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | エディタシーンビュー | 主画面 | シーンツリーの視覚的な構築・編集 |
| - | ゲーム実行ウィンドウ | 結果表示画面 | シーンツリーの実行結果表示 |

## 機能種別

エンジンコア機能 / ライフサイクル管理 / イベント駆動処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| p_time | double | Yes | フレーム間の経過時間（秒） | 正の数値 |
| p_physics | bool | Yes | 物理処理フレームかどうか | - |
| p_group | StringName | Yes | グループ名 | 空でないこと |
| p_notification | int | Yes | 通知タイプ | 有効な通知定数 |
| p_call_flags | uint32_t | No | グループ呼び出しフラグ | GROUP_CALL_* の組み合わせ |
| p_path | String | Yes | シーンファイルパス | 有効なリソースパス |
| p_scene | PackedScene | Yes | パック済みシーン | null不可 |
| p_delay_sec | double | Yes | タイマー遅延秒数 | 正の数値 |

### 入力データソース

- MainLoop からのコールバック（process, physics_process）
- ユーザースクリプトからのAPI呼び出し
- エンジン内部からの通知

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| root | Window* | ルートウィンドウノード |
| current_scene | Node* | 現在のシーンノード |
| frame | int64_t | 現在のフレーム番号 |
| node_count | int | ツリー内のノード総数 |
| nodes_in_group | Vector<Node*> | 指定グループ内のノード一覧 |
| timer | SceneTreeTimer | 作成されたタイマー |
| tween | Tween | 作成されたTween |

### 出力先

- ノードへの通知（NOTIFICATION_PROCESS等）
- シグナルの発行（tree_changed, node_added, scene_changed等）
- RenderingServerへの補間データ

## 処理フロー

### 処理シーケンス

```
1. 初期化 (initialize)
   └─ ルートウィンドウをツリーに設定

2. 物理処理ループ (physics_process)
   ├─ フレームカウンタ増加
   ├─ 変換通知のフラッシュ
   ├─ physics_frame シグナル発行
   ├─ ピッキングビューポートの処理
   ├─ ノードグループの処理 (_process)
   ├─ 遅延グループ呼び出しのフラッシュ
   ├─ メッセージキューのフラッシュ
   ├─ タイマーとTweenの処理
   └─ 削除キューのフラッシュ

3. 通常処理ループ (process)
   ├─ FTI（固定タイムステップ補間）更新
   ├─ マルチプレイヤーポーリング
   ├─ process_frame シグナル発行
   ├─ ノードグループの処理 (_process)
   ├─ シーン切り替えのフラッシュ
   ├─ タイマーとTweenの処理
   ├─ 削除キューのフラッシュ
   └─ アクセシビリティ更新

4. 終了処理 (finalize)
   ├─ 削除キューのフラッシュ
   ├─ ルートノードの削除
   ├─ タイマーとTweenのクリーンアップ
   └─ MainLoopの終了処理
```

### フローチャート

```mermaid
flowchart TD
    A[ゲーム起動] --> B[SceneTree::initialize]
    B --> C[root->_set_tree]
    C --> D{メインループ開始}

    D --> E[iteration_prepare]
    E --> F[physics_process]
    F --> G[iteration_end]
    G --> H[process]
    H --> I{終了要求?}

    I -->|No| D
    I -->|Yes| J[finalize]
    J --> K[root削除]
    K --> L[終了]

    subgraph physics_process
        F1[flush_transform_notifications]
        F2[emit physics_frame]
        F3[_process true]
        F4[process_timers]
        F5[_flush_delete_queue]
    end

    subgraph process
        P1[FTI update]
        P2[multiplayer poll]
        P3[emit process_frame]
        P4[_process false]
        P5[_flush_scene_change]
    end
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | メインスレッド制限 | シーン切り替え、ポーズ設定はメインスレッドからのみ実行可能 | 常時 |
| BR-002 | ポーズ継承 | ポーズ状態はノードのprocess_modeに従って子ノードに影響 | ポーズ時 |
| BR-003 | グループ順序 | グループ内ノードはツリー順序でソートされる | グループ呼び出し時 |
| BR-004 | 遅延削除 | queue_delete で登録されたオブジェクトはフレーム終了時に削除 | 常時 |
| BR-005 | シーン遷移遅延 | シーン切り替えは即座ではなく、フレーム処理後に実行 | シーン変更時 |

### 計算ロジック

**タイマー残り時間の計算**:
```
time_left = time_left - (ignore_time_scale ? unscaled_delta : p_delta)
```

**プロセスグループのソート**:
- process_thread_group_order による優先度ソート
- 同一優先度内ではスレッドグループタイプでソート

## データベース操作仕様

本機能はデータベースを使用しない。メモリ内のデータ構造のみで動作する。

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ERR_INVALID_PARAMETER | パラメータエラー | メインスレッド以外からのシーン変更 | メインスレッドで呼び出す |
| ERR_CANT_OPEN | ファイルエラー | シーンファイルが読み込めない | ファイルパスを確認 |
| ERR_CANT_CREATE | 生成エラー | シーンのインスタンス化失敗 | シーンデータを確認 |
| ERR_UNCONFIGURED | 状態エラー | リロード時にcurrent_sceneがnull | シーンを先にロード |

### リトライ仕様

シーンロード失敗時のリトライ機構は提供されていない。呼び出し側で適切にエラーハンドリングする必要がある。

## トランザクション仕様

本機能はデータベーストランザクションを使用しない。ただし、以下の操作は原子性が保証される:

- グループ操作中のノード削除検知（nodes_removed_on_group_call_lock）
- スレッドセーフメソッド（_THREAD_SAFE_METHOD_）によるロック

## パフォーマンス要件

- フレームレート維持のため、process/physics_processは可能な限り高速に実行
- グループ呼び出し時はノードリストをコピーして安全性を確保
- プロセスグループのソートは変更時のみ実行（dirty flag使用）
- スレッドグループによる並列処理対応

## セキュリティ考慮事項

- queue_delete による安全なオブジェクト削除（即時削除による参照破壊を防止）
- スレッドセーフティのためのミューテックスロック
- メインスレッド制限による競合状態の防止

## 備考

- Godot 4.0以降、notify_group()とset_group()はデフォルトで即時実行（GROUP_CALL_DEFERRED不要）
- 物理補間はエディタ内では無効化される
- ProcessGroupによるスレッド分散処理が可能

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

シーンツリーの内部データ構造を把握することが、全体理解の基盤となる。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | scene_tree.h | `scene/main/scene_tree.h` | クラス定義、メンバ変数、Group構造体の理解 |

**読解のコツ**:
- `Group`構造体（122-125行）がノードグループの基本単位
- `ProcessGroup`構造体（96-105行）が処理グループの管理単位
- `group_map`（149行）がグループ名とGroupの対応マップ

**主要データ構造**:
- **134行**: `Window *root` - ツリーのルートウィンドウ
- **149行**: `HashMap<StringName, Group> group_map` - グループ管理マップ
- **113行**: `LocalVector<ProcessGroup *> process_groups` - 処理グループリスト
- **219行**: `List<Ref<SceneTreeTimer>> timers` - タイマーリスト
- **220行**: `List<Ref<Tween>> tweens` - Tweenリスト

#### Step 2: エントリーポイントを理解する

MainLoopから呼び出されるメインエントリーポイントを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | scene_tree.cpp | `scene/main/scene_tree.cpp` | initialize, process, physics_process の実装 |

**主要処理フロー**:
1. **575-580行**: `initialize()` - ツリー初期化、ルートノードをツリーに設定
2. **628-660行**: `physics_process()` - 物理フレーム処理のメインループ
3. **677-780行**: `process()` - 通常フレーム処理のメインループ
4. **844-873行**: `finalize()` - 終了処理、リソース解放

#### Step 3: グループ管理を理解する

ノードグループの追加・削除・呼び出し処理を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | scene_tree.cpp | `scene/main/scene_tree.cpp` | add_to_group, remove_from_group, call_group_flagsp |

**主要処理フロー**:
- **167-179行**: `add_to_group()` - ノードをグループに追加
- **181-191行**: `remove_from_group()` - ノードをグループから削除
- **350-441行**: `call_group_flagsp()` - グループ内ノードへのメソッド呼び出し
- **333-348行**: `_update_group_order()` - グループ内ノードのソート

#### Step 4: プロセスグループ処理を理解する

マルチスレッド対応の処理グループシステムを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | scene_tree.cpp | `scene/main/scene_tree.cpp` | _process, _process_group の実装 |

**主要処理フロー**:
- **1151-1210行**: `_process_group()` - 単一グループの処理実行
- **1218-1334行**: `_process()` - 全グループの処理オーケストレーション
- **1212-1216行**: `_process_groups_thread()` - スレッドワーカー関数

#### Step 5: シーン管理を理解する

シーンの切り替え・リロード・アンロード処理を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | scene_tree.cpp | `scene/main/scene_tree.cpp` | change_scene_to_*, _flush_scene_change |

**主要処理フロー**:
- **1677-1685行**: `change_scene_to_file()` - ファイルパスからシーン切り替え
- **1687-1694行**: `change_scene_to_packed()` - PackedSceneからシーン切り替え
- **1696-1719行**: `change_scene_to_node()` - ノードへの直接切り替え
- **1647-1675行**: `_flush_scene_change()` - 遅延シーン切り替えの実行

#### Step 6: タイマー・Tween処理を理解する

時間ベースの処理管理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | scene_tree.cpp | `scene/main/scene_tree.cpp` | process_timers, process_tweens, create_timer |

**主要処理フロー**:
- **782-812行**: `process_timers()` - タイマーの更新とタイムアウト処理
- **814-842行**: `process_tweens()` - Tweenアニメーションの更新
- **1742-1752行**: `create_timer()` - 新規タイマーの作成

### プログラム呼び出し階層図

```
SceneTree (MainLoop継承)
    │
    ├─ initialize()
    │      └─ root->_set_tree(this)
    │
    ├─ iteration_prepare()
    │      ├─ flush_transform_notifications()
    │      └─ scene_tree_fti.tick_update()
    │
    ├─ physics_process(p_time)
    │      ├─ flush_transform_notifications()
    │      ├─ MainLoop::physics_process()
    │      ├─ emit_signal("physics_frame")
    │      ├─ call_group("_picking_viewports", "_process_picking")
    │      ├─ _process(true)
    │      │      ├─ _process_group() [for each group]
    │      │      │      ├─ call_queue.flush()
    │      │      │      └─ node->notification(NOTIFICATION_*_PROCESS)
    │      │      └─ WorkerThreadPool [if threaded]
    │      ├─ _flush_ugc()
    │      ├─ MessageQueue::flush()
    │      ├─ process_timers()
    │      ├─ process_tweens()
    │      └─ _flush_delete_queue()
    │
    ├─ iteration_end()
    │      └─ _client_physics_interpolation.physics_process()
    │
    ├─ process(p_time)
    │      ├─ scene_tree_fti.frame_update()
    │      ├─ MainLoop::process()
    │      ├─ multiplayer->poll()
    │      ├─ emit_signal("process_frame")
    │      ├─ _process(false)
    │      ├─ _flush_scene_change()
    │      ├─ process_timers()
    │      ├─ process_tweens()
    │      ├─ _flush_delete_queue()
    │      └─ _flush_accessibility_changes()
    │
    └─ finalize()
           ├─ _flush_delete_queue()
           ├─ root->_set_tree(nullptr)
           ├─ memdelete(root)
           └─ MainLoop::finalize()
```

### データフロー図

```
[入力]                      [処理]                           [出力]

フレーム時間(delta) ──────▶ SceneTree::process() ──────────▶ ノードへの通知
                               │                              (NOTIFICATION_PROCESS)
                               ▼
                          process_groups ─────────────────▶ 各ノードの_process()実行
                               │
                               ▼
                          process_timers() ───────────────▶ timeout シグナル発行
                               │
                               ▼
                          process_tweens() ───────────────▶ Tweenステップ実行

PackedScene ─────────────▶ change_scene_to_packed() ──────▶ current_scene 更新
                               │                              │
                               ▼                              ▼
                          _flush_scene_change() ──────────▶ scene_changed シグナル

グループ名 + メソッド ───▶ call_group_flagsp() ───────────▶ グループ内全ノードへの
                               │                              メソッド呼び出し
                               ▼
                          _update_group_order()
                               │
                               ▼
                          node->callp() [for each]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| scene_tree.cpp | `scene/main/scene_tree.cpp` | ソース | SceneTreeクラスの実装 |
| scene_tree.h | `scene/main/scene_tree.h` | ヘッダ | SceneTreeクラスの定義 |
| scene_tree_fti.h | `scene/main/scene_tree_fti.h` | ヘッダ | 固定タイムステップ補間 |
| node.cpp | `scene/main/node.cpp` | ソース | ノードの基本実装 |
| node.h | `scene/main/node.h` | ヘッダ | ノードの基本定義 |
| main_loop.cpp | `core/os/main_loop.cpp` | ソース | MainLoop基底クラス |
| main_loop.h | `core/os/main_loop.h` | ヘッダ | MainLoop基底クラス定義 |
| viewport.cpp | `scene/main/viewport.cpp` | ソース | ビューポート実装 |
| window.cpp | `scene/main/window.cpp` | ソース | ウィンドウ実装 |
| message_queue.cpp | `core/object/message_queue.cpp` | ソース | メッセージキュー |
| packed_scene.cpp | `scene/resources/packed_scene.cpp` | ソース | パック済みシーン |
| tween.cpp | `scene/animation/tween.cpp` | ソース | Tweenアニメーション |
| multiplayer_api.cpp | `scene/main/multiplayer_api.cpp` | ソース | マルチプレイヤーAPI |
