# 通知設計書 19-NOTIFICATION_PROCESS

## 概要

本ドキュメントは、Godotエンジンにおける `NOTIFICATION_PROCESS` 通知の設計と実装について記述する。この通知はNodeクラスの基本的な処理ループ通知の一つで、アイドル処理（フレーム更新）時に毎フレーム発火する、ゲームロジックの中心となる通知機構である。

### 本通知の処理概要

`NOTIFICATION_PROCESS` は、Godotのメインループにおいて、物理処理の後のアイドル処理フェーズで送信される通知である。この通知は、set_process(true)が呼ばれたノードに対して、毎フレーム送信される。フレームレートに依存した処理（アニメーション、UI更新、入力応答など）を実装するために使用される。

**業務上の目的・背景**：ゲームやアプリケーションにおいて、継続的な更新処理は不可欠である。NOTIFICATION_PROCESSは、ビジュアルの更新、UI状態の管理、入力のポーリング、時間ベースのアニメーションなど、フレームごとに実行する必要がある処理のためのフックを提供する。

**通知の送信タイミング**：NOTIFICATION_PROCESSは、メインループの各フレームで、物理処理の後に送信される。デルタタイム（前フレームからの経過時間）が利用可能で、get_process_delta_time()で取得できる。

**通知の受信者**：set_process(true)が呼ばれ、かつシーンツリー内にあるすべてのNodeおよびその派生クラスが受信者となる。処理優先度（process_priority）に基づいてソートされた順序で通知が送信される。

**通知内容の概要**：通知値は整数定数17（Node::NOTIFICATION_PROCESS）として定義されている。追加のパラメータは含まれないが、get_process_delta_time()でデルタタイムを取得可能。

**期待されるアクション**：受信者は、フレームごとの更新処理を実行する。デルタタイムを使用してフレームレート非依存の処理を実装することが推奨される。

## 通知種別

Nodeフレーム更新通知（内部通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | process_priorityに依存 |
| リトライ | 無 |
| 通知値 | 17 |

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

set_process(true)が呼ばれたノードに対して、process_priorityの昇順（小さい値が先）で送信される。同じ優先度のノードはツリー順で処理される。

## 通知テンプレート

### 定数定義

```cpp
enum {
    // ...
    NOTIFICATION_PHYSICS_PROCESS = 16,
    NOTIFICATION_PROCESS = 17,
    // ...
};
```

### GDScript使用例

```gdscript
extends Node2D

func _ready():
    # 処理を有効化（_process()をオーバーライドすると自動的に有効化される）
    set_process(true)

func _process(delta: float):
    # 毎フレーム実行される処理
    # delta = 前フレームからの経過時間（秒）

    # 位置の更新（フレームレート非依存）
    position.x += 100 * delta  # 1秒あたり100ピクセル移動

    # アニメーション更新
    rotation += PI * delta  # 1秒あたり180度回転

# または_notification()を使用
func _notification(what):
    if what == NOTIFICATION_PROCESS:
        var delta = get_process_delta_time()
        _custom_process(delta)

func _custom_process(delta: float):
    # カスタム処理
    pass
```

### 典型的な使用パターン

```gdscript
extends CharacterBody2D

@export var speed := 200.0

func _process(delta: float):
    # 入力の取得
    var input_dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")

    # 移動ベクトルの計算
    velocity = input_dir * speed

    # UI更新
    $HealthBar.value = health

    # デバッグ情報の更新
    $DebugLabel.text = "FPS: %d" % Engine.get_frames_per_second()
```

### 処理の有効化/無効化

```gdscript
extends Node

var _is_active := true

func _ready():
    # 処理を有効化
    set_process(true)

func _process(delta: float):
    if _is_active:
        # アクティブ時の処理
        pass

func pause():
    # 処理を一時停止
    set_process(false)

func resume():
    # 処理を再開
    set_process(true)
```

## テンプレート変数

NOTIFICATION_PROCESSはパラメータを持たないため、テンプレート変数は存在しない。ただし、以下のメソッドで関連情報を取得可能。

| メソッド | 戻り値 | 説明 |
|---------|-------|------|
| get_process_delta_time() | double | 前フレームからの経過時間（秒） |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| フレーム更新 | メインループのアイドルフェーズ | set_process(true) かつ can_process() | 毎フレーム実行 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| set_process(false) | 処理が無効化されている |
| can_process() == false | ProcessModeによりポーズ/無効状態 |
| シーンツリー外 | ノードがシーンツリーに入っていない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[メインループ] --> B[物理処理フェーズ]
    B --> C[アイドル処理フェーズ]
    C --> D[SceneTree::_process]
    D --> E[process_groups処理]
    E --> F{各ノードをイテレート}
    F --> G{can_process?}
    G -->|Yes| H[notification PROCESS]
    H --> I[GDVIRTUAL_CALL _process]
    I --> J[次のノード]
    G -->|No| J
    J --> F
    F -->|完了| K[フレーム終了]
```

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

### 参照テーブル一覧

該当なし（NOTIFICATION_PROCESSはデータベースを使用しない）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 特になし | - | - |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| フレームレート | ディスプレイのリフレッシュレートまたはプロジェクト設定に依存 |
| 最大FPS | Application/Run/Max FPS設定（0=無制限） |

### 配信時間帯

制限なし（メインループ実行中は常に送信）

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

- _process()内で長時間のブロッキング処理を行うとフレームレートが低下する
- 重い処理はワーカースレッドやcall_deferred()で非同期化することを推奨
- 無限ループや再帰に注意

## 備考

- _process()をオーバーライドすると、NOTIFICATION_READYで自動的にset_process(true)が呼ばれる
- set_process_priority()で処理順序を制御可能（小さい値が先に実行）
- NOTIFICATION_INTERNAL_PROCESS（値25）はエンジン内部用の別の処理通知
- 物理処理はNOTIFICATION_PHYSICS_PROCESS（値16）を使用

---

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

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

### 推奨読解順序

#### Step 1: 定数定義を理解する

通知値の定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | node.h | `scene/main/node.h` | NOTIFICATION_PROCESS定数の定義 |

**主要処理フロー**:
- **458行目**: `NOTIFICATION_PROCESS = 17`

#### Step 2: 通知ハンドラを理解する

_notification()でのPROCESS処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | node.cpp | `scene/main/node.cpp` | _notification()内のNOTIFICATION_PROCESS処理 |

**主要処理フロー**:
- **91-93行目**: case NOTIFICATION_PROCESS
- **92行目**: `GDVIRTUAL_CALL(_process, get_process_delta_time())`

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

SceneTreeでの処理グループ管理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | scene_tree.cpp | `scene/main/scene_tree.cpp` | _process関数での処理グループ呼び出し |

#### Step 4: set_process()を理解する

処理の有効化/無効化の仕組みを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | node.cpp | `scene/main/node.cpp` | set_process()関数の実装 |

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

```
メインループ
    │
    ├─ 物理処理フェーズ
    │
    └─ アイドル処理フェーズ
           │
           └─ SceneTree::_process()
                  │
                  └─ ProcessGroup処理
                         │
                         └─ 各ノード（priority順）
                                │
                                ├─ can_process()チェック
                                │
                                ├─ notification(NOTIFICATION_PROCESS)
                                │      └─ Node::_notification()
                                │             └─ GDVIRTUAL_CALL(_process, delta)
                                │                    └─ GDScript: _process(delta)
                                │
                                └─ 次のノードへ
```

### データフロー図

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

フレーム開始            ───▶ メインループ           ───▶ 物理処理
                                    │
前フレーム時刻          ───▶ デルタタイム計算      ───▶ delta値
                                    │
                                    └─▶ アイドル処理フェーズ
                                            │
                                            └─▶ SceneTree::_process()
                                                    │
                                                    ├─▶ priority順ソート
                                                    │
                                                    └─▶ 各ノードに通知
                                                            │
                                                            └─▶ _process(delta)
                                                                    │
                                                                    └─▶ ゲームロジック実行
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| node.h | `scene/main/node.h` | ヘッダ | Node クラス定義、NOTIFICATION_PROCESS定数 |
| node.cpp | `scene/main/node.cpp` | ソース | _notification()、set_process()実装 |
| scene_tree.h | `scene/main/scene_tree.h` | ヘッダ | SceneTreeクラス定義 |
| scene_tree.cpp | `scene/main/scene_tree.cpp` | ソース | _process()、処理グループ管理 |
| main_loop.h | `core/main/main_loop.h` | ヘッダ | MainLoopクラス定義 |
| Node.xml | `doc/classes/Node.xml` | ドキュメント | APIリファレンス |
