Design Pattern / Game Programming

[ゲームプログラミング] Event Queue パターン

イベントの発行と消費をキューで分離することで、システム間の結合度を下げるパターンです。

  • Design Pattern
  • Game Programming
目次

パターンの一行要約

イベントの発行と消費をキューで分離することで、システム間の結合度を下げるパターンです。

Unityでの典型的な使用例

  • 戦闘イベントをUI、サウンド、報酬に同時に伝える必要がある場合。
  • 即時の直接呼び出しによる強い結合を減らしたい場合。

構成要素(役割)

  • Publisher: イベントの発行者
  • Queue: イベントの保管場所
  • Consumer: フレーム単位の処理者

Unityサンプル(C#)

以下のコードは、上で説明したシナリオに基づいた簡略化されたUnityのサンプルです。

using System.Collections.Generic;
using UnityEngine;

public readonly struct CombatEvent
{
    public readonly string EventType;
    public readonly int Value;

    public CombatEvent(string eventType, int value)
    {
        EventType = eventType;
        Value = value;
    }
}

public sealed class CombatEventQueue : MonoBehaviour
{
    private readonly Queue<CombatEvent> pendingEvents = new();

    public void Publish(CombatEvent combatEvent)
    {
        pendingEvents.Enqueue(combatEvent);
    }

    private void Update()
    {
        while (pendingEvents.Count > 0)
        {
            CombatEvent combatEvent = pendingEvents.Dequeue();
            Debug.Log($"${combatEvent.EventType}: ${combatEvent.Value}");
        }
    }
}

利点

  • 発行者と消費者のタイミングを分離し、システム間の直接的な依存関係を減らせます。
  • イベントログ、リプレイ、バッチ処理などの拡張が容易になります。

注意点

  • キューが滞留すると、レイテンシの増加によって応答性が低下する可能性があります。
  • 順序や重複のルールを明確に定義しないと、再現が難しいバグが発生することがあります。

相互作用図

発行者と消費者がキューによって分離される非同期な流れを示します。

flowchart LR

  queue["Event Queue"]

  subgraph producers["Producers"]
    combat["CombatSystem"]
    ai["AISystem"]
    loot["LootSystem"]
  end

  subgraph consumers["Consumers"]
    ui["UISystem"]
    audio["AudioSystem"]
    analytics["AnalyticsSystem"]
  end

  combat -->|enqueue| queue
  ai -->|enqueue| queue
  loot -->|enqueue| queue
  queue -->|dequeue| ui
  queue -->|dequeue| audio
  queue -->|dequeue| analytics

コメント