# 通知設計書 43-NOTIFICATION_EXIT_WORLD

## 概要

本ドキュメントは、Godotエンジンにおける `NOTIFICATION_EXIT_WORLD` 通知の設計仕様を記述する。この通知はNode3D通知の一種であり、3DノードがWorld3Dから登録解除された際に送信される。

### 本通知の処理概要

`NOTIFICATION_EXIT_WORLD` は、Node3Dおよびその派生クラスのノードが3Dワールドから退出した（登録解除された）ことを通知するためのシステム通知である。

**業務上の目的・背景**：3Dゲームやアプリケーションにおいて、3Dオブジェクトがワールドから削除される際にクリーンアップ処理を行う必要がある。例えば、物理ボディのワールドからの登録解除、描画リソースのシナリオからのデタッチ、カメラやライトの無効化などが挙げられる。この通知により、リソースリークを防ぎ、適切なクリーンアップ処理を実行できる。逆順（子から親へ）で送信されることで、依存関係を持つリソースの安全な解放が保証される。

**通知の送信タイミング**：Node3DがSceneTreeから削除される際、NOTIFICATION_EXIT_TREEの処理中に送信される。具体的には、node_3d.cppの206行目で`notification(NOTIFICATION_EXIT_WORLD, true)`が呼び出される。第2引数のtrueは逆順伝播を示す。

**通知の受信者**：Node3Dクラスおよびそのすべての派生クラス（VisualInstance3D、CollisionObject3D、Camera3D、Light3Dなど）。

**通知内容の概要**：整数値42（NOTIFICATION_EXIT_WORLD）が通知される。追加のパラメータは含まれない。

**期待されるアクション**：受信したノードは、3Dワールドから退出するためのクリーンアップ処理を行う。VisualInstance3Dではインスタンスをシナリオから解除し、CollisionObject3Dでは物理ワールドからの登録解除を行う。また、スクリプトで`_exit_world()`メソッドが定義されている場合、そのメソッドが呼び出される。

## 通知種別

Godotエンジン内部通知（Node3D通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 通知値 | 42 |
| 送信方式 | 同期（notification呼び出し） |
| 伝播方向 | 逆順（子から親へ）で処理される |
| 対象クラス | Node3Dおよびその派生クラス |

### 送信先決定ロジック

NOTIFICATION_EXIT_TREEの処理中に、自ノードに対して送信される。notification()の第2引数に`true`を指定することで、逆順で通知が処理される。

## 通知テンプレート

### 定数定義

| 項目 | 内容 |
|-----|------|
| 定義ファイル | scene/3d/node_3d.h |
| 定数名 | NOTIFICATION_EXIT_WORLD |
| 値 | 42 |

### 使用例

```gdscript
func _notification(what):
    if what == NOTIFICATION_EXIT_WORLD:
        # 3Dワールドから出る時の処理
        _cleanup_3d_resources()
```

```cpp
void Custom3DNode::_notification(int p_what) {
    switch (p_what) {
        case NOTIFICATION_EXIT_WORLD: {
            // 3Dワールドから出る時の処理
            _cleanup_3d_resources();
        } break;
    }
}
```

### スクリプトコールバック

```gdscript
# スクリプトで_exit_world()を定義すると自動的に呼び出される
func _exit_world():
    print("Exited 3D world")
```

## テンプレート変数

この通知には追加のパラメータは含まれない。

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| p_what | 通知種別（42） | 直接渡される | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ツリー削除 | NOTIFICATION_EXIT_TREE | Node3Dがツリーから削除される時 | EXIT_TREEの処理中に送信 |
| ワールド変更 | ワールドの切り替え | 現在のWorld3Dから離れる時 | Viewport移動時など |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| ツリー外 | 既にSceneTreeに存在しない場合は送信されない |
| inside_world == false | 既にワールド外の場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[Node3D削除] --> B[NOTIFICATION_EXIT_TREE]
    B --> C[FTI通知<br/>node_3d_notify_delete]
    C --> D[notification<br/>NOTIFICATION_EXIT_WORLD, true]
    D --> E[xform_change_listから削除]
    E --> F[親ノードのchildren更新]
    F --> G[_update_visibility_parent]
    G --> H[終了]
```

## データベース参照・更新仕様

本通知はGodotエンジンの内部通知であり、データベースへのアクセスは行わない。

### 内部状態更新

| 状態変数 | 操作 | 備考 |
|---------|------|------|
| data.inside_world | false設定 | 271行目 |
| data.viewport | nullptr設定 | 272行目 |

### 派生クラスでの処理例

#### VisualInstance3D

| 処理 | 内容 |
|-----|------|
| シナリオ解除 | RenderingServer::instance_set_scenario(RID()) |
| スケルトンデタッチ | RenderingServer::instance_attach_skeleton(RID()) |
| 可視性更新 | _set_vi_visible(false) |

#### Camera3D

| 処理 | 内容 |
|-----|------|
| Viewportからのカメラ解除 | 現在のカメラ設定を解除 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| メインスレッド違反 | メインスレッド以外から呼び出し | ERR_MAIN_THREAD_GUARDマクロでエラー出力 |

### スレッド安全性

| 項目 | 内容 |
|-----|------|
| スレッド制限 | メインスレッドのみ |
| ガード | ERR_MAIN_THREAD_GUARD |

## 配信設定

### プラットフォーム対応

| プラットフォーム | 対応状況 | 備考 |
|----------------|---------|------|
| 全プラットフォーム | 対応 | 3D機能を持つすべてのプラットフォーム |

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

本通知はエンジン内部の3Dノード管理に使用されるものであり、セキュリティ上の特別な考慮事項はない。

## 備考

- NOTIFICATION_ENTER_WORLD（値=41）と対になる通知
- 逆順で送信される（第2引数がtrue）
- Node3D.xmlのドキュメントで公式に記載されている
- ギズモのクリア処理がエディタ環境で実行される

---

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

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

### 推奨読解順序

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

まず、Node3Dクラスの通知定数定義を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | node_3d.h | `scene/3d/node_3d.h` | NOTIFICATION_EXIT_WORLD = 42 の定義を確認 |
| 1-2 | Node3D.xml | `doc/classes/Node3D.xml` | 381-383行目: 公式ドキュメントの記述を確認 |

**読解のコツ**: Node3D.hのenum定義部分を参照し、NOTIFICATION_ENTER_WORLD（41）との関係を把握する。

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

処理の起点となるnode_3d.cppの_notification()を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | node_3d.cpp | `scene/3d/node_3d.cpp` | NOTIFICATION_EXIT_TREE caseの処理を理解 |

**主要処理フロー**:
1. **199-233行目**: NOTIFICATION_EXIT_TREEの処理
2. **200行目**: ERR_MAIN_THREAD_GUARD
3. **202-204行目**: FTI（Frame Time Interpolation）への通知
4. **206行目**: `notification(NOTIFICATION_EXIT_WORLD, true)` の呼び出し（逆順）

#### Step 3: EXIT_WORLDハンドラを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | node_3d.cpp | `scene/3d/node_3d.cpp` | NOTIFICATION_EXIT_WORLD caseの処理（260-273行目） |

**主要処理フロー**:
- **260行目**: ERR_MAIN_THREAD_GUARD
- **262-264行目**: エディタでのギズモクリア
- **266-269行目**: スクリプトの_exit_world()呼び出し
- **271-272行目**: inside_world = false, viewport = nullptr

#### Step 4: 派生クラスでの処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | visual_instance_3d.cpp | `scene/3d/visual_instance_3d.cpp` | NOTIFICATION_EXIT_WORLDでのシナリオ解除処理（107-111行目） |

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

```
Node3D::_notification(NOTIFICATION_EXIT_TREE)
    │
    ├─ get_tree()->get_scene_tree_fti().node_3d_notify_delete(this)
    │
    ├─ notification(NOTIFICATION_EXIT_WORLD, true)  // 逆順
    │      │
    │      └─ Node3D::_notification(NOTIFICATION_EXIT_WORLD)
    │             │
    │             ├─ clear_gizmos() [TOOLS_ENABLED]
    │             ├─ script->call("_exit_world")
    │             ├─ data.inside_world = false
    │             └─ data.viewport = nullptr
    │
    ├─ xform_change_list.remove()
    │
    └─ _update_visibility_parent(true)
```

### データフロー図

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

SceneTree削除 ───▶ Node3D                      ───▶ inside_world = false
                   ::EXIT_TREE処理                    + viewport = nullptr
                          │
                          ▼
                   notification(EXIT_WORLD, true)
                          │
                          ▼
                   EXIT_WORLDハンドラ ───▶ _exit_world()
                          │                    コールバック
                          ▼
                   派生クラスの処理 ───▶ RenderingServerからの
                   (VisualInstance3D等)    リソース解除
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| node_3d.h | `scene/3d/node_3d.h` | ヘッダー | NOTIFICATION_EXIT_WORLD定数定義 |
| node_3d.cpp | `scene/3d/node_3d.cpp` | ソース | 通知送信（206行目）、ハンドラ（260-273行目） |
| visual_instance_3d.cpp | `scene/3d/visual_instance_3d.cpp` | ソース | シナリオ解除処理（107-111行目） |
| camera_3d.cpp | `scene/3d/camera_3d.cpp` | ソース | カメラのワールド解除処理 |
| Node3D.xml | `doc/classes/Node3D.xml` | ドキュメント | 通知の公式ドキュメント（381-383行目） |
